You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2015/07/08 23:06:36 UTC

[1/8] allura git commit: [#6373] use sphinxcontrib.programoutput to document paster commands. Improve some usage help text

Repository: allura
Updated Branches:
  refs/heads/db/6373 4cd8fc312 -> 2842760f6 (forced update)


[#6373] use sphinxcontrib.programoutput to document paster commands.  Improve some usage help text


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/1be59741
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/1be59741
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/1be59741

Branch: refs/heads/db/6373
Commit: 1be597416d002b2c5f93af47a4b2d4290e1cb2d0
Parents: be3845c
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jul 7 18:10:13 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:48 2015 -0400

----------------------------------------------------------------------
 Allura/allura/command/show_models.py           |  4 +-
 Allura/allura/command/taskd_cleanup.py         |  2 +-
 Allura/docs/conf.py                            |  1 +
 Allura/docs/getting_started/administration.rst | 73 ++++++++++++++++++++-
 ForgeBlog/forgeblog/command/rssfeeds.py        |  2 +-
 ForgeChat/forgechat/command.py                 |  2 +-
 requirements.txt                               |  1 +
 scripts/create-allura-sitemap.py               |  2 +-
 8 files changed, 80 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/Allura/allura/command/show_models.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index d941e9e..89a2a88 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -53,7 +53,7 @@ class ReindexCommand(base.Command):
     min_args = 1
     max_args = 1
     usage = '<ini file>'
-    summary = 'Reindex and re-shortlink all artifacts'
+    summary = 'Reindex into solr and re-shortlink all artifacts'
     parser = base.Command.standard_parser(verbose=True)
     parser.add_option('-p', '--project', dest='project',  default=None,
                       help='project to reindex')
@@ -203,7 +203,7 @@ class EnsureIndexCommand(base.Command):
     min_args = 1
     max_args = 1
     usage = '[<ini file>]'
-    summary = 'Run ensure_index on all mongo objects'
+    summary = 'Create all the Mongo indexes specified by Ming models, drop any unspecified indexes.'
     parser = base.Command.standard_parser(verbose=True)
 
     def command(self):

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/Allura/allura/command/taskd_cleanup.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/taskd_cleanup.py b/Allura/allura/command/taskd_cleanup.py
index 47d09bf..a796e6c 100644
--- a/Allura/allura/command/taskd_cleanup.py
+++ b/Allura/allura/command/taskd_cleanup.py
@@ -27,7 +27,7 @@ import base
 
 
 class TaskdCleanupCommand(base.Command):
-    summary = 'Tasks cleanup command'
+    summary = 'Tasks cleanup command.  Determines which taskd processes are handling tasks, and what has been dropped or got hung.'
     parser = base.Command.standard_parser(verbose=True)
     parser.add_option('-k', '--kill-stuck-taskd',
                       dest='kill', action='store_true',

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/Allura/docs/conf.py
----------------------------------------------------------------------
diff --git a/Allura/docs/conf.py b/Allura/docs/conf.py
index 4c55afa..aa69905 100644
--- a/Allura/docs/conf.py
+++ b/Allura/docs/conf.py
@@ -42,6 +42,7 @@ import os
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
               'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig']
 extensions += ['sphinxarg.ext']
+extensions += ['sphinxcontrib.programoutput']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index e8952b9..b199277 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -70,7 +70,71 @@ running a script via this interface, the `args/kwargs` JSON should be like::
 
 See the listing of :mod:`some available tasks <allura.tasks.admin_tasks>`.
 
-Available scripts and tasks are:
+
+Available scripts and commands are:
+
+
+create-neighborhood
+-------------------
+
+.. program-output:: paster create-neighborhood development.ini --help
+
+
+ensure_index
+------------
+
+.. program-output:: paster ensure_index development.ini --help
+
+
+ircbot
+------
+
+.. program-output:: paster ircbot development.ini --help
+
+
+reindex
+-------
+
+.. program-output:: paster reindex development.ini --help
+
+
+set-neighborhood-features
+-------------------------
+
+.. program-output:: paster set-neighborhood-features development.ini --help
+
+
+set-tool-access
+---------------
+
+.. program-output:: paster set-tool-access development.ini --help
+
+
+taskd
+-----
+
+.. program-output:: paster taskd development.ini --help
+
+
+taskd_cleanup
+-------------
+
+.. program-output:: paster taskd_cleanup development.ini --help
+
+
+pull-rss-feeds
+--------------
+
+Blog tools may optionally be configured to fetch external RSS feeds.  If that is in place, this command should
+be used to fetch all those rss feeds and convert new entries into blog posts.
+
+Requires `html2text`, a GPL library.
+
+::
+
+    cd ../ForgeBlog
+    paster pull-rss-feeds development.ini --help
+
 
 disable_users.py
 ----------------
@@ -82,6 +146,7 @@ disable_users.py
     :func: get_parser
     :prog: paster script development.ini allura/scripts/disable_users.py --
 
+
 refreshrepo.py
 --------------
 
@@ -92,6 +157,7 @@ refreshrepo.py
     :func: get_parser
     :prog: paster script development.ini allura/scripts/refreshrepo.py --
 
+
 reindex_projects.py
 -------------------
 
@@ -102,6 +168,7 @@ reindex_projects.py
     :func: get_parser
     :prog: paster script development.ini allura/scripts/reindex_projects.py --
 
+
 reindex_users.py
 ----------------
 
@@ -112,6 +179,7 @@ reindex_users.py
     :func: get_parser
     :prog: paster script development.ini allura/scripts/reindex_users.py --
 
+
 create-allura-sitemap.py
 ------------------------
 
@@ -122,6 +190,7 @@ create-allura-sitemap.py
     :func: parser
     :prog: paster script development.ini ../scripts/create-allura-sitemap.py --
 
+
 publicize-neighborhood.py
 -------------------------
 
@@ -132,6 +201,7 @@ publicize-neighborhood.py
     :func: parser
     :prog: paster script development.ini ../scripts/publicize-neighborhood.py --
 
+
 scrub-allura-data.py
 --------------------
 
@@ -142,6 +212,7 @@ scrub-allura-data.py
     :func: parser
     :prog: paster script development.ini ../scripts/scrub-allura-data.py --
 
+
 teamforge-import.py
 -------------------
 

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/ForgeBlog/forgeblog/command/rssfeeds.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/command/rssfeeds.py b/ForgeBlog/forgeblog/command/rssfeeds.py
index 7771a5c..42b5edd 100644
--- a/ForgeBlog/forgeblog/command/rssfeeds.py
+++ b/ForgeBlog/forgeblog/command/rssfeeds.py
@@ -46,7 +46,7 @@ html2text.BODY_WIDTH = 0
 
 
 class RssFeedsCommand(base.BlogCommand):
-    summary = 'Rss feed client'
+    summary = 'Fetch external rss feeds for all Blog tools, and convert new feed entries into blog posts'
     parser = base.BlogCommand.standard_parser(verbose=True)
     parser.add_option('-a', '--appid', dest='appid', default='',
                       help='application id')

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/ForgeChat/forgechat/command.py
----------------------------------------------------------------------
diff --git a/ForgeChat/forgechat/command.py b/ForgeChat/forgechat/command.py
index 6af2eaa..da2faf8 100644
--- a/ForgeChat/forgechat/command.py
+++ b/ForgeChat/forgechat/command.py
@@ -43,7 +43,7 @@ class IRCBotCommand(allura.command.Command):
     min_args = 1
     max_args = 1
     usage = '<ini file>'
-    summary = 'Connect to all configured IRC servers and relay messages'
+    summary = 'For the ForgeChat tool.  Connect to all configured IRC servers and relay messages'
     parser = command.Command.standard_parser(verbose=True)
     parser.add_option('-c', '--context', dest='context',
                       help=('The context of the message (path to the project'

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index 80eda02..77581e2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -81,3 +81,4 @@ q==2.3
 WebError==0.10.3
 -e git://github.com/brondsem/sphinx-argparse.git#egg=sphinx-argparse   # pending merge requests
 sphinx-rtd-theme==0.1.6
+sphinxcontrib-programoutput==0.8
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/1be59741/scripts/create-allura-sitemap.py
----------------------------------------------------------------------
diff --git a/scripts/create-allura-sitemap.py b/scripts/create-allura-sitemap.py
index 29220d1..9ab8f38 100644
--- a/scripts/create-allura-sitemap.py
+++ b/scripts/create-allura-sitemap.py
@@ -16,7 +16,7 @@
 #       under the License.
 
 """
-Generate Allura sitemap xml files.
+Generate Allura sitemap xml files.  You will need to configure your webserver to serve the files.
 
 This takes a while to run on a prod-sized data set. There are a couple of
 things that would make it faster, if we need/want to.


[2/8] allura git commit: [#6373] cross link our different APIs

Posted by br...@apache.org.
[#6373] cross link our different APIs


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/be3845c3
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/be3845c3
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/be3845c3

Branch: refs/heads/db/6373
Commit: be3845c3d60e2c42e7040067590745db0c052fa2
Parents: acd50e8
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jul 7 16:34:18 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:48 2015 -0400

----------------------------------------------------------------------
 Allura/docs/api/index.rst                      | 4 ++++
 Allura/docs/getting_started/administration.rst | 1 +
 2 files changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/be3845c3/Allura/docs/api/index.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/api/index.rst b/Allura/docs/api/index.rst
index 2103410..451972a 100644
--- a/Allura/docs/api/index.rst
+++ b/Allura/docs/api/index.rst
@@ -19,6 +19,10 @@
 Allura API
 **********
 
+This documents the python classes available to Allura tools and extensions.
+
+If you are looking for the web REST API, see :ref:`public_api`
+
 
 .. toctree::
     :maxdepth: 3

http://git-wip-us.apache.org/repos/asf/allura/blob/be3845c3/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index 0b03728..e8952b9 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -200,6 +200,7 @@ users, projects, and tools on Allura.  However, SourceForge has help docs that c
 these functions https://sourceforge.net/p/forge/documentation/Docs%20Home/  Note
 that this documentation also covers some SourceForge features that are not part of Allura.
 
+.. _public_api:
 
 Public API Documentation
 ========================


[7/8] allura git commit: [#6373] write some docs about admin webpages

Posted by br...@apache.org.
[#6373] write some docs about admin webpages


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b253cdd4
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b253cdd4
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b253cdd4

Branch: refs/heads/db/6373
Commit: b253cdd4d28532623b4a7e7681d4dc04141123df
Parents: 848355c
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 8 16:56:45 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:50 2015 -0400

----------------------------------------------------------------------
 Allura/docs/getting_started/administration.rst | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b253cdd4/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index c0b23e2..d9044b1 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -22,6 +22,25 @@ Administration
 .. contents::
    :local:
 
+
+Site Admin Interface
+====================
+
+Allura has an admin interface at http://MYSITE/nf/admin/  You must be an admin of the
+`/p/allura` project on the site to access it.  If you want to use another project to control
+admin access, change the :code:`site_admin_project` setting in :file:`development.ini`.
+
+The admin interface allows you to:
+
+* View newly registered projects
+* Search for projects
+* View neighborhood total stats
+* Search for users, view user details, update user status, email address, and reset their password
+* View background task statuses, and submit new background tasks
+* Manage "trove" categories (for user skill choices)
+* Subscriber a user to an artifact
+* Reclone a repository
+
 Commands, Scripts, and Tasks
 ============================
 


[5/8] allura git commit: [#6373] add more client script documentation

Posted by br...@apache.org.
[#6373] add more client script documentation


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/848355c6
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/848355c6
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/848355c6

Branch: refs/heads/db/6373
Commit: 848355c61831a4e9a5d02f6964d867ab9fc80c3e
Parents: 3189602
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 8 15:59:52 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:50 2015 -0400

----------------------------------------------------------------------
 Allura/docs/getting_started/administration.rst | 31 ++++++++++---
 scripts/new_ticket.py                          | 48 ++++++++++++---------
 scripts/wiki-copy.py                           |  3 +-
 scripts/wiki-post.py                           |  2 +-
 4 files changed, 54 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/848355c6/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index 1a2084f..c0b23e2 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -233,16 +233,33 @@ Requires running: :command:`pip install suds` first. ::
 Client Scripts
 ==============
 
-Allura includes some client scripts that use Allura APIs and do not have to be run
-from an Allura server.  They do require various python packages to be installed
-and possibly a local Allura codebase set up.
+Allura includes some client scripts that demonstrate use of the Allura REST API and do not have to be run
+from an Allura environment.  They do require some python packages to be installed, though.
 
-One such script is `wiki-copy.py` which reads the wiki pages from one Allura wiki
-instance and uploads them to another Allura wiki instance.  It can be run as:
 
-.. code-block:: console
+wiki-copy.py
+------------
+
+.. program-output:: python ../../scripts/wiki-copy.py --help | sed 's/Usage: /Usage: python scripts\//'
+    :shell:
+
+
+new_ticket.py
+-------------
+
+Illustrates creating a new ticket, using the simple OAuth Bearer token.
+
+.. argparse::
+    :file: ../../scripts/new_ticket.py
+    :func: get_parser
+    :prog: python scripts/new_ticket.py
+
+
+wiki-post.py
+------------
 
-    $ python scripts/wiki-copy.py --help
+.. program-output:: python ../../scripts/wiki-post.py --help | sed 's/Usage: /Usage: python scripts\//'
+    :shell:
 
 
 Site Notifications

http://git-wip-us.apache.org/repos/asf/allura/blob/848355c6/scripts/new_ticket.py
----------------------------------------------------------------------
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 9b23328..924f9d2 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -22,32 +22,38 @@ import requests
 from pprint import pprint
 
 
-def get_opts():
+def get_parser():
     parser = argparse.ArgumentParser(
         description='Post a new ticket using the API')
     parser.add_argument('project', help='Project shortname')
     parser.add_argument('mount_point', help='Tracker mount point')
-    parser.add_argument('-H', '--host', default='sourceforge.net')
-    opts = parser.parse_args()
+    parser.add_argument('-H', '--host', default='sourceforge.net', help='Base domain')
+    return parser
+
+
+def get_opts():
+    opts = get_parser().parse_args()
     opts.url = 'https://{}/rest/p/{}/{}/new'.format(opts.host,
                                                     opts.project, opts.mount_point)
     return opts
 
-opts = get_opts()
-access_token = raw_input('Access (bearer) token: ')
-summary = raw_input('Summary: ')
-print 'Description (C-d to end):'
-print '-----------------------------------------------'
-description = sys.stdin.read()
-print '-----------------------------------------------'
-
-r = requests.post(opts.url, params={
-    'access_token': access_token,
-    'ticket_form.summary': summary,
-    'ticket_form.description': description,
-})
-if r.status_code == 200:
-    print 'Ticket created at: %s' % r.url
-    pprint(r.json())
-else:
-    print 'Error [%s]:\n%s' % (r.status_code, r.text)
+
+if __name__ == '__main__':
+    opts = get_opts()
+    access_token = raw_input('Access (bearer) token: ')
+    summary = raw_input('Summary: ')
+    print 'Description (C-d to end):'
+    print '-----------------------------------------------'
+    description = sys.stdin.read()
+    print '-----------------------------------------------'
+
+    r = requests.post(opts.url, params={
+        'access_token': access_token,
+        'ticket_form.summary': summary,
+        'ticket_form.description': description,
+    })
+    if r.status_code == 200:
+        print 'Ticket created at: %s' % r.url
+        pprint(r.json())
+    else:
+        print 'Error [%s]:\n%s' % (r.status_code, r.text)

http://git-wip-us.apache.org/repos/asf/allura/blob/848355c6/scripts/wiki-copy.py
----------------------------------------------------------------------
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 0692852..26304cb 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -30,7 +30,8 @@ import oauth2 as oauth
 
 
 def main():
-    op = OptionParser(usage='usage: %prog [options]')
+    op = OptionParser(usage='usage: %prog [options]',
+                      description='Reads the wiki pages from one Allura wiki instance and uploads them to another Allura wiki instance.')
     op.add_option('-f', '--from-wiki', action='store', dest='from_wiki',
                   help='URL of wiki API to copy from like http://fromserver.com/rest/p/test/wiki/')
     op.add_option('-t', '--to-wiki', action='store', dest='to_wiki',

http://git-wip-us.apache.org/repos/asf/allura/blob/848355c6/scripts/wiki-post.py
----------------------------------------------------------------------
diff --git a/scripts/wiki-post.py b/scripts/wiki-post.py
index 7e16bb1..2a6fb40 100755
--- a/scripts/wiki-post.py
+++ b/scripts/wiki-post.py
@@ -85,7 +85,7 @@ class Signer(object):
 
 def main():
     usage = 'usage: %prog [options] [PageName [file]]'
-    op = OptionParser(usage=usage)
+    op = OptionParser(usage=usage, description='Use a markdown file to create/update a wiki page')
     op.add_option('-c', '--config', metavar='CONFIG')
     op.add_option('-t', '--token', metavar='TOKEN')
     op.add_option('', '--anon', action='store_true')


[4/8] allura git commit: [#6373] wrap output so it doesn't create horizontal scrolls

Posted by br...@apache.org.
[#6373] wrap output so it doesn't create horizontal scrolls


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/c95885e0
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c95885e0
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c95885e0

Branch: refs/heads/db/6373
Commit: c95885e05991618a2597482ea31820de65c3dde7
Parents: 1be5974
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 8 10:28:44 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:49 2015 -0400

----------------------------------------------------------------------
 Allura/docs/getting_started/administration.rst | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/c95885e0/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index b199277..1a2084f 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -77,7 +77,8 @@ Available scripts and commands are:
 create-neighborhood
 -------------------
 
-.. program-output:: paster create-neighborhood development.ini --help
+.. program-output:: paster create-neighborhood development.ini --help | fmt -s -w 95
+   :shell:
 
 
 ensure_index
@@ -101,13 +102,15 @@ reindex
 set-neighborhood-features
 -------------------------
 
-.. program-output:: paster set-neighborhood-features development.ini --help
+.. program-output:: paster set-neighborhood-features development.ini --help | fmt -s -w 95
+   :shell:
 
 
 set-tool-access
 ---------------
 
-.. program-output:: paster set-tool-access development.ini --help
+.. program-output:: paster set-tool-access development.ini --help | fmt -s -w 95
+   :shell:
 
 
 taskd
@@ -119,7 +122,8 @@ taskd
 taskd_cleanup
 -------------
 
-.. program-output:: paster taskd_cleanup development.ini --help
+.. program-output:: paster taskd_cleanup development.ini --help | fmt -s -w 95
+   :shell:
 
 
 pull-rss-feeds


[3/8] allura git commit: [#6373] document common admin scripts

Posted by br...@apache.org.
[#6373] document common admin scripts


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/acd50e8d
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/acd50e8d
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/acd50e8d

Branch: refs/heads/db/6373
Commit: acd50e8d8e1cb00a5413f6a9caa227b401ff12b4
Parents: 93a1ecc
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 1 12:49:45 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:48 2015 -0400

----------------------------------------------------------------------
 Allura/allura/scripts/disable_users.py         |   3 +
 Allura/allura/scripts/refreshrepo.py           |   4 +
 Allura/allura/scripts/reindex_projects.py      |   6 +-
 Allura/allura/scripts/reindex_users.py         |   6 +-
 Allura/docs/conf.py                            |   3 +-
 Allura/docs/getting_started/administration.rst | 126 +++++++++++++++++---
 requirements.txt                               |   1 +
 scripts/create-allura-sitemap.py               |   7 +-
 scripts/publicize-neighborhood.py              |   9 +-
 scripts/scrub-allura-data.py                   |  13 +-
 10 files changed, 151 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/allura/scripts/disable_users.py
----------------------------------------------------------------------
diff --git a/Allura/allura/scripts/disable_users.py b/Allura/allura/scripts/disable_users.py
index 7eeef33..ed93833 100644
--- a/Allura/allura/scripts/disable_users.py
+++ b/Allura/allura/scripts/disable_users.py
@@ -66,5 +66,8 @@ class DisableUsers(ScriptTask):
         return parser
 
 
+def get_parser():
+    return DisableUsers.parser()
+
 if __name__ == '__main__':
     DisableUsers.main()

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/allura/scripts/refreshrepo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/scripts/refreshrepo.py b/Allura/allura/scripts/refreshrepo.py
index a336b0d..fbec016 100644
--- a/Allura/allura/scripts/refreshrepo.py
+++ b/Allura/allura/scripts/refreshrepo.py
@@ -194,6 +194,10 @@ class RefreshRepo(ScriptTask):
         return parser
 
 
+def get_parser():
+    return RefreshRepo.parser()
+
+
 if __name__ == '__main__':
     faulthandler.enable()
     RefreshRepo.main()

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/allura/scripts/reindex_projects.py
----------------------------------------------------------------------
diff --git a/Allura/allura/scripts/reindex_projects.py b/Allura/allura/scripts/reindex_projects.py
index 89c447e..0f8f3be 100644
--- a/Allura/allura/scripts/reindex_projects.py
+++ b/Allura/allura/scripts/reindex_projects.py
@@ -87,7 +87,7 @@ class ReindexProjects(ScriptTask):
 
     @classmethod
     def parser(cls):
-        parser = argparse.ArgumentParser(description='Reindex all projects')
+        parser = argparse.ArgumentParser(description='Reindex all project records into Solr (for searching)')
         parser.add_argument('-n', '--nbhd', action='store', default='', dest='nbhd',
                             help='Restrict reindex to a particular neighborhood, e.g. /p/.')
         parser.add_argument(
@@ -109,5 +109,9 @@ class ReindexProjects(ScriptTask):
         return parser
 
 
+def get_parser():
+    return ReindexProjects.parser()
+
+
 if __name__ == '__main__':
     ReindexProjects.main()

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/allura/scripts/reindex_users.py
----------------------------------------------------------------------
diff --git a/Allura/allura/scripts/reindex_users.py b/Allura/allura/scripts/reindex_users.py
index 8a0762b..e2acd3b 100644
--- a/Allura/allura/scripts/reindex_users.py
+++ b/Allura/allura/scripts/reindex_users.py
@@ -73,7 +73,7 @@ class ReindexUsers(ScriptTask):
 
     @classmethod
     def parser(cls):
-        parser = argparse.ArgumentParser(description='Reindex all users')
+        parser = argparse.ArgumentParser(description='Reindex all users into Solr (for searching)')
         parser.add_argument('--dry-run', action='store_true', dest='dry_run',
                             default=False, help='Log names of projects that would be reindexed, '
                             'but do not perform the actual reindex.')
@@ -85,5 +85,9 @@ class ReindexUsers(ScriptTask):
         return parser
 
 
+def get_parser():
+    return ReindexUsers.parser()
+
+
 if __name__ == '__main__':
     ReindexUsers.main()

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/docs/conf.py
----------------------------------------------------------------------
diff --git a/Allura/docs/conf.py b/Allura/docs/conf.py
index c201b9c..4c55afa 100644
--- a/Allura/docs/conf.py
+++ b/Allura/docs/conf.py
@@ -41,6 +41,7 @@ import os
 
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
               'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig']
+extensions += ['sphinxarg.ext']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -56,7 +57,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = 'Apache Allura'
-copyright = '2012-2014 The Apache Software Foundation'
+copyright = '2012-2015 The Apache Software Foundation'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index 4410f55..0b03728 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -19,13 +19,19 @@
 Administration
 **************
 
+.. contents::
+   :local:
+
 Commands, Scripts, and Tasks
-----------------------------
+============================
+
+Overview
+--------
 
-Allura has many `paster` commands and `paster` scripts that can be run from the
-server commandline to administrate Allura.  There are also tasks that can be
-run through the `taskd` system.  New tasks can be submitted via the web at
-/nf/admin/task_manager  Some paster commands and scripts have been set up
+Allura has many commands and scripts that can be run from the server commandline to
+administrate Allura.  There are also tasks that can be run through the `taskd` system
+in the background.  These tasks can be submitted via the web at
+http://MYSITE/nf/admin/task_manager  Some paster scripts have been set up
 so that they are runnable as tasks too, giving you the convenience of starting
 them through the web and letting `taskd` execute them, rather than from a server
 shell.
@@ -42,30 +48,116 @@ Commands can be discovered and run via the `paster` command when you are in the
      paster create-neighborhood development.ini myneighborhood myuser ...
 
 
-Scripts are in the `scripts/` directory and run via `paster script`.  An extra
-`--` is required to separate script arguments from paster arguments.  Example::
+Scripts are in the `scripts/` directory and run slightly differently, via `paster script`.  An extra
+:kbd:`--` is required to separate script arguments from paster arguments.  Example::
 
      paster script development.ini ../scripts/create-allura-sitemap.py -- --help
     ... help output ...
 
      paster script development.ini ../scripts/create-allura-sitemap.py -- -u 100
 
-TODO:   explain important scripts, commands
-
-Tasks can be run via the web interface at /nf/admin/task_manager  You must know
-the full task name, e.g. `allura.tasks.admin_tasks.install_app`  You can
+Tasks can be run via the web interface at http://MYSITE/nf/admin/task_manager  You must know
+the full task name, e.g. :code:`allura.tasks.admin_tasks.install_app`  You can
 optionally provide a username and project and app which will get set on the
 current context (`c`).  You should specify what args and kwargs will be passed
-as parameters to the task.  They are specified in JSON format on the form.
+as parameters to the task.  They are specified in JSON format on the form.  If you are
+running a script via this interface, the `args/kwargs` JSON should be like::
+
+    {
+        "args": ["--foo --bar baz"],
+        "kwargs": {}
+    }
 
 See the listing of :mod:`some available tasks <allura.tasks.admin_tasks>`.
 
-TODO: explain how to run scripttasks and commandtasks
+Available scripts and tasks are:
 
+disable_users.py
+----------------
 
-Client Scripts
+*Can be run as a background task using task name:* :code:`allura.scripts.disable_users.DisableUsers`
+
+.. argparse::
+    :module: allura.scripts.disable_users
+    :func: get_parser
+    :prog: paster script development.ini allura/scripts/disable_users.py --
+
+refreshrepo.py
 --------------
 
+*Can be run as a background task using task name:* :code:`allura.scripts.refreshrepo.RefreshRepo`
+
+.. argparse::
+    :module: allura.scripts.refreshrepo
+    :func: get_parser
+    :prog: paster script development.ini allura/scripts/refreshrepo.py --
+
+reindex_projects.py
+-------------------
+
+*Can be run as a background task using task name:* :code:`allura.scripts.reindex_projects.ReindexProjects`
+
+.. argparse::
+    :module: allura.scripts.reindex_projects
+    :func: get_parser
+    :prog: paster script development.ini allura/scripts/reindex_projects.py --
+
+reindex_users.py
+----------------
+
+*Can be run as a background task using task name:* :code:`allura.scripts.reindex_users.ReindexUsers`
+
+.. argparse::
+    :module: allura.scripts.reindex_users
+    :func: get_parser
+    :prog: paster script development.ini allura/scripts/reindex_users.py --
+
+create-allura-sitemap.py
+------------------------
+
+*Cannot currently be run as a background task.*
+
+.. argparse::
+    :file: ../../scripts/create-allura-sitemap.py
+    :func: parser
+    :prog: paster script development.ini ../scripts/create-allura-sitemap.py --
+
+publicize-neighborhood.py
+-------------------------
+
+*Cannot currently be run as a background task.*
+
+.. argparse::
+    :file: ../../scripts/publicize-neighborhood.py
+    :func: parser
+    :prog: paster script development.ini ../scripts/publicize-neighborhood.py --
+
+scrub-allura-data.py
+--------------------
+
+*Cannot currently be run as a background task.*
+
+.. argparse::
+    :file: ../../scripts/scrub-allura-data.py
+    :func: parser
+    :prog: paster script development.ini ../scripts/scrub-allura-data.py --
+
+teamforge-import.py
+-------------------
+
+*Cannot currently be run as a background task.*
+
+Extract data from a TeamForge site (via its web API), and import directly into Allura.  There are some hard-coded
+and extra functions in this script, which should be removed or updated before being used again.
+Requires running: :command:`pip install suds` first. ::
+
+    usage: paster script development.ini ../scripts/teamforge-import.py -- --help
+
+
+
+Client Scripts
+==============
+
 Allura includes some client scripts that use Allura APIs and do not have to be run
 from an Allura server.  They do require various python packages to be installed
 and possibly a local Allura codebase set up.
@@ -79,7 +171,7 @@ instance and uploads them to another Allura wiki instance.  It can be run as:
 
 
 Site Notifications
-------------------
+==================
 
 Allura has support for site-wide notifications that appear below the site header,
 but there is currently no UI for managing them.  They can easily be inserted via
@@ -101,7 +193,7 @@ no notification will be shown.
 
 
 Using Projects and Tools
-------------------------
+========================
 
 We currently don't have any further documentation for basic operations of managing
 users, projects, and tools on Allura.  However, SourceForge has help docs that cover
@@ -110,6 +202,6 @@ that this documentation also covers some SourceForge features that are not part
 
 
 Public API Documentation
-------------------------
+========================
 
 Allura's web api is currently documented at https://sourceforge.net/p/forge/documentation/Allura%20API/

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index fffb91d..80eda02 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -79,4 +79,5 @@ WebTest==1.4.0
 testfixtures==3.0.0
 q==2.3
 WebError==0.10.3
+-e git://github.com/brondsem/sphinx-argparse.git#egg=sphinx-argparse   # pending merge requests
 sphinx-rtd-theme==0.1.6

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/scripts/create-allura-sitemap.py
----------------------------------------------------------------------
diff --git a/scripts/create-allura-sitemap.py b/scripts/create-allura-sitemap.py
index f39b2a6..29220d1 100644
--- a/scripts/create-allura-sitemap.py
+++ b/scripts/create-allura-sitemap.py
@@ -142,7 +142,7 @@ def main(options):
             f.write(sitemap_index_content)
 
 
-def parse_options():
+def parser():
     import argparse
     class Validate(argparse.Action):
         def __call__(self, parser, namespace, value, option_string=None):
@@ -165,8 +165,11 @@ def parse_options():
     parser.add_argument('-n', '--neighborhood', dest='neighborhood',
                          help="URL prefix of excluded neighborhood(s)",
                          default=None, nargs='*')
+    return parser
+
+def parse_options():
+    return parser().parse_args()
 
-    return parser.parse_args()
 
 if __name__ == '__main__':
     sys.exit(main(parse_options()))

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/scripts/publicize-neighborhood.py
----------------------------------------------------------------------
diff --git a/scripts/publicize-neighborhood.py b/scripts/publicize-neighborhood.py
index c32d384..9cc6494 100644
--- a/scripts/publicize-neighborhood.py
+++ b/scripts/publicize-neighborhood.py
@@ -70,7 +70,7 @@ def main(options):
     return 0
 
 
-def parse_options():
+def parser():
     import argparse
     parser = argparse.ArgumentParser(
         description='Make all projects in a neighborhood public.')
@@ -81,7 +81,12 @@ def parse_options():
                         help='Run in test mode (no updates will be applied).')
     parser.add_argument('--log', dest='log_level', default='INFO',
                         help='Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL).')
-    return parser.parse_args()
+    return parser
+
+
+def parse_options():
+    return parser().parse_args()
+
 
 if __name__ == '__main__':
     sys.exit(main(parse_options()))

http://git-wip-us.apache.org/repos/asf/allura/blob/acd50e8d/scripts/scrub-allura-data.py
----------------------------------------------------------------------
diff --git a/scripts/scrub-allura-data.py b/scripts/scrub-allura-data.py
index c0e0828..211cfdc 100644
--- a/scripts/scrub-allura-data.py
+++ b/scripts/scrub-allura-data.py
@@ -134,16 +134,23 @@ def main(options):
     return 0
 
 
-def parse_options():
+def parser():
     import argparse
     parser = argparse.ArgumentParser(
-        description='Removes private data from the Allura MongoDB.')
+        description='Removes private data from the Allura MongoDB.  DO NOT RUN THIS on your main database.  '
+                    'This is intended to be used on a copy of your database, to prepare it for sharing with others.'
+    )
     parser.add_argument('--dry-run', dest='dry_run', default=False,
                         action='store_true',
                         help='Run in test mode (no updates will be applied).')
     parser.add_argument('--log', dest='log_level', default='INFO',
                         help='Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL).')
-    return parser.parse_args()
+    return parser
+
+
+def parse_options():
+    return parser().parse_args()
+
 
 if __name__ == '__main__':
     sys.exit(main(parse_options()))


[8/8] allura git commit: [#6373] move Client Scripts section below Public API

Posted by br...@apache.org.
[#6373] move Client Scripts section below Public API


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2842760f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2842760f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2842760f

Branch: refs/heads/db/6373
Commit: 2842760f68c2230adbd0f0f6f5bec69786b1334f
Parents: b253cdd
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 8 16:57:04 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:51 2015 -0400

----------------------------------------------------------------------
 Allura/docs/getting_started/administration.rst | 66 ++++++++++-----------
 1 file changed, 33 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2842760f/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index d9044b1..abbe814 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -248,39 +248,6 @@ Requires running: :command:`pip install suds` first. ::
     usage: paster script development.ini ../scripts/teamforge-import.py -- --help
 
 
-
-Client Scripts
-==============
-
-Allura includes some client scripts that demonstrate use of the Allura REST API and do not have to be run
-from an Allura environment.  They do require some python packages to be installed, though.
-
-
-wiki-copy.py
-------------
-
-.. program-output:: python ../../scripts/wiki-copy.py --help | sed 's/Usage: /Usage: python scripts\//'
-    :shell:
-
-
-new_ticket.py
--------------
-
-Illustrates creating a new ticket, using the simple OAuth Bearer token.
-
-.. argparse::
-    :file: ../../scripts/new_ticket.py
-    :func: get_parser
-    :prog: python scripts/new_ticket.py
-
-
-wiki-post.py
-------------
-
-.. program-output:: python ../../scripts/wiki-post.py --help | sed 's/Usage: /Usage: python scripts\//'
-    :shell:
-
-
 Site Notifications
 ==================
 
@@ -311,9 +278,42 @@ users, projects, and tools on Allura.  However, SourceForge has help docs that c
 these functions https://sourceforge.net/p/forge/documentation/Docs%20Home/  Note
 that this documentation also covers some SourceForge features that are not part of Allura.
 
+
 .. _public_api:
 
 Public API Documentation
 ========================
 
 Allura's web api is currently documented at https://sourceforge.net/p/forge/documentation/Allura%20API/
+
+
+Client Scripts
+==============
+
+Allura includes some client scripts that demonstrate use of the Allura REST API and do not have to be run
+from an Allura environment.  They do require some python packages to be installed, though.
+
+
+wiki-copy.py
+------------
+
+.. program-output:: python ../../scripts/wiki-copy.py --help | sed 's/Usage: /Usage: python scripts\//'
+    :shell:
+
+
+new_ticket.py
+-------------
+
+Illustrates creating a new ticket, using the simple OAuth Bearer token.
+
+.. argparse::
+    :file: ../../scripts/new_ticket.py
+    :func: get_parser
+    :prog: python scripts/new_ticket.py
+
+
+wiki-post.py
+------------
+
+.. program-output:: python ../../scripts/wiki-post.py --help | sed 's/Usage: /Usage: python scripts\//'
+    :shell:
\ No newline at end of file


[6/8] allura git commit: [#6373] delete scripts that are no longer needed. Rename to clarify a few

Posted by br...@apache.org.
[#6373] delete scripts that are no longer needed.  Rename to clarify a few


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/3189602c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/3189602c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/3189602c

Branch: refs/heads/db/6373
Commit: 3189602c97b6c04414b60cbf1cfaf82893dc2437
Parents: c95885e
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Jul 8 15:59:29 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Jul 8 17:00:50 2015 -0400

----------------------------------------------------------------------
 scripts/allura_import.py                     | 119 ------------------
 scripts/import_trove_categories.py           |  48 -------
 scripts/open_relay.py                        |  89 -------------
 scripts/prep-scm-sandbox.py                  |  94 --------------
 scripts/prepare-allura-tickets-for-import.py | 147 ----------------------
 scripts/recover-user-databases.py            |  72 -----------
 scripts/setup-scm-server.py                  | 127 -------------------
 scripts/trac_export_wiki.py                  |  56 +++++++++
 scripts/trac_import.py                       | 119 ++++++++++++++++++
 scripts/wiki-export.py                       |  56 ---------
 10 files changed, 175 insertions(+), 752 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/allura_import.py
----------------------------------------------------------------------
diff --git a/scripts/allura_import.py b/scripts/allura_import.py
deleted file mode 100644
index d4e51fd..0000000
--- a/scripts/allura_import.py
+++ /dev/null
@@ -1,119 +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 json
-from optparse import OptionParser
-
-from allura.lib.import_api import AlluraImportApiClient
-from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki
-
-
-def main():
-    optparser, options, args = parse_options()
-
-    import_options = {}
-    for s in options.import_opts:
-        k, v = s.split('=', 1)
-        if v == 'false':
-            v = False
-        import_options[k] = v
-
-    user_map = {}
-    if options.user_map_file:
-        f = open(options.user_map_file)
-        try:
-            user_map = json.load(f)
-            if type(user_map) is not type({}):
-                raise ValueError
-            for k, v in user_map.iteritems():
-                print k, v
-                if not isinstance(k, basestring) or not isinstance(v, basestring):
-                    raise ValueError
-        except ValueError:
-            optparser.error(
-                '--user-map should specify JSON file with format {"original_user": "sf_user", ...}')
-        finally:
-            f.close()
-
-    import_options['user_map'] = user_map
-
-    cli = AlluraImportApiClient(options.base_url, options.token, options.verbose)
-    doc_txt = open(args[0]).read()
-
-    if options.forum:
-        import_forum(cli, options.project, options.forum, user_map, doc_txt,
-                     validate=options.validate, neighborhood=options.neighborhood)
-    elif options.wiki:
-        import_wiki(cli, options.project, options.wiki, options, doc_txt)
-
-
-
-def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
-        neighborhood='p'):
-    url = '/rest/{neighborhood}/{project}/{tool}'.format(
-            neighborhood=neighborhood,
-            project=project,
-            tool=tool,
-            )
-    if validate:
-        url += '/validate_import'
-        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
-    else:
-        url += '/perform_import'
-        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
-
-
-def parse_options():
-    optparser = OptionParser(usage='''%prog [options] <JSON dump>
-
-Import project data dump in JSON format into an Allura project.''')
-    optparser.add_option('-t', '--token', dest='token',
-                         help='OAuth bearer token (generate at /auth/oauth/)')
-    optparser.add_option('-p', '--project', dest='project',
-                         help='Project to import to')
-    optparser.add_option('-n', '--neighborhood', dest='neighborhood',
-                         help="URL prefix of destination neighborhood (default is 'p')",
-                         default='p')
-    optparser.add_option('-f', '--forum', dest='forum',
-                         help='Forum tool to import to')
-    optparser.add_option('-w', '--wiki', dest='wiki',
-                         help='Wiki tool to import to')
-    optparser.add_option('-u', '--base-url', dest='base_url',
-                         default='https://sourceforge.net', help='Base Allura URL (%default)')
-    optparser.add_option('-o', dest='import_opts',
-                         default=[], action='append', help='Specify import option(s)', metavar='opt=val')
-    optparser.add_option('--user-map', dest='user_map_file',
-                         help='Map original users to SF.net users', metavar='JSON_FILE')
-    optparser.add_option('--validate', dest='validate',
-                         action='store_true', help='Validate import data')
-    optparser.add_option('-v', '--verbose', dest='verbose',
-                         action='store_true', help='Verbose operation')
-    optparser.add_option('-c', '--continue', dest='cont',
-                         action='store_true', help='Continue import into existing tracker')
-    options, args = optparser.parse_args()
-    if len(args) != 1:
-        optparser.error("Wrong number of arguments")
-    if not options.token:
-        optparser.error("OAuth bearer token is required")
-    if not options.project:
-        optparser.error("Target project is required")
-    options.neighborhood = options.neighborhood.strip('/')
-    return optparser, options, args
-
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/import_trove_categories.py
----------------------------------------------------------------------
diff --git a/scripts/import_trove_categories.py b/scripts/import_trove_categories.py
deleted file mode 100644
index 123a56c..0000000
--- a/scripts/import_trove_categories.py
+++ /dev/null
@@ -1,48 +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 tg import config
-
-from ming.orm import session
-
-import sfx
-from allura import model as M
-from allura.lib import helpers as h
-from sfx.model import tables as T
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    sfx.middleware.configure_databases(h.config_with_prefix(config, 'sfx.'))
-    topic_trove = T.trove_cat.select(
-        T.trove_cat.c.shortname == 'topic').execute().fetchone()
-    M.ProjectCategory.query.remove()
-    for t in T.trove_cat.select(
-            T.trove_cat.c.parent == topic_trove.trove_cat_id).execute():
-        parent = M.ProjectCategory(
-            name=t.shortname, label=t.fullname, description=t.description)
-        for tt in T.trove_cat.select(
-                T.trove_cat.c.parent == t.trove_cat_id).execute():
-            M.ProjectCategory(parent_id=parent._id,
-                              name=tt.shortname, label=tt.fullname, description=tt.description)
-    session(M.ProjectCategory).flush()
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/open_relay.py
----------------------------------------------------------------------
diff --git a/scripts/open_relay.py b/scripts/open_relay.py
deleted file mode 100644
index ba21862..0000000
--- a/scripts/open_relay.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-
-#       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
-import os
-import smtpd
-import smtplib
-import asyncore
-from ConfigParser import ConfigParser
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    cp = ConfigParser()
-    log.info('Read config from: %s',
-             cp.read([os.path.join(os.environ['HOME'], '.open_relay.ini')]))
-    host = cp.get('open_relay', 'host')
-    port = cp.getint('open_relay', 'port')
-    ssl = cp.getboolean('open_relay', 'ssl')
-    tls = cp.getboolean('open_relay', 'tls')
-    username = cp.get('open_relay', 'username')
-    password = cp.get('open_relay', 'password')
-    smtp_client = MailClient(host,
-                             port,
-                             ssl, tls,
-                             username, password)
-    MailServer(('0.0.0.0', 8826), None,
-               smtp_client=smtp_client)
-    asyncore.loop()
-
-
-class MailClient(object):
-
-    def __init__(self, host, port, ssl, tls, username, password):
-        self.host, self.port, self.ssl, self.tls, self.username, self.password = \
-            host, port, ssl, tls, username, password
-        self._client = None
-        self._connect()
-
-    def sendmail(self, mailfrom, rcpttos, data):
-        if str(mailfrom) == 'None':
-            mailfrom = rcpttos[0]
-        log.info('Sending mail to %s' % rcpttos)
-        log.info('Sending mail from %s' % mailfrom)
-        try:
-            self._client.sendmail(mailfrom, rcpttos, data)
-        except:
-            self._connect()
-            self._client.sendmail(mailfrom, rcpttos, data)
-
-    def _connect(self):
-        if self.ssl:
-            self._client = smtplib.SMTP_SSL(self.host, int(self.port))
-        else:
-            self._client = smtplib.SMTP(self.host, int(self.port))
-        if self.tls:
-            self._client.starttls()
-        if self.username:
-            self._client.login(self.username, self.password)
-
-
-class MailServer(smtpd.SMTPServer):
-
-    def __init__(self, *args, **kwargs):
-        self._client = kwargs.pop('smtp_client')
-        smtpd.SMTPServer.__init__(self, *args, **kwargs)
-
-    def process_message(self, peer, mailfrom, rcpttos, data):
-        self._client.sendmail(mailfrom, rcpttos, data)
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/prep-scm-sandbox.py
----------------------------------------------------------------------
diff --git a/scripts/prep-scm-sandbox.py b/scripts/prep-scm-sandbox.py
deleted file mode 100644
index 414280f..0000000
--- a/scripts/prep-scm-sandbox.py
+++ /dev/null
@@ -1,94 +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 os
-import string
-
-HOME = os.environ['HOME']
-
-USERS = ['user%.2d' % i for i in range(1, 21)]
-USERS += [
-    'admin1', 'admin2',
-    'dovethunder', 'dovetail', 'dovestream', 'dovetree', 'dovespangle',
-    'dovemeade', 'dovestar', 'dovebuyer', 'dovesomething', 'dovesweet', 'dovewood']
-SSH_CONFIG = '%s/.ssh/config' % HOME
-LDIF_FILE = '%s/users.ldif' % HOME
-KEYFILE = '%s/.ssh/allura_rsa' % HOME
-
-
-def main():
-
-    # Generate ssh key for SCM login
-    os.system('cp %s %s.bak' % (SSH_CONFIG, SSH_CONFIG))
-    with open(SSH_CONFIG) as fp:
-        lines = fp.readlines()
-    new_lines = [
-        SSH_TMPL.substitute(
-            sb_host=sb_host,
-            sb=sb,
-            veid='%d0%.2d' % (sb_host, sb))
-        for sb_host in 5, 6, 7, 9
-        for sb in range(99)]
-    new_lines = '\n'.join(new_lines)
-    found_star = False
-    with open(SSH_CONFIG, 'w') as fp:
-        for line in lines:
-            if not found_star and line.startswith('Host *'):
-                print >> fp, new_lines
-                found_star = True
-            print >> fp, line.rstrip()
-        if not found_star:
-            print >> fp, new_lines
-    os.system("ssh-keygen -t rsa -b 2048 -N '' -f %s" % KEYFILE)
-
-    # Generate ldif
-    pubkey = open(KEYFILE + '.pub').read()
-    with open(LDIF_FILE, 'w') as fp:
-        for user in USERS:
-            print >> fp, LDIF_TMPL.substitute(
-                user=user, pubkey=pubkey)
-
-    # Update LDAP
-    assert 0 == os.system('/usr/local/sbin/ldaptool modify -v -f %s' %
-                          LDIF_FILE)
-
-SSH_TMPL = string.Template('''
-Host hg*-$veid hg*-${veid}.sb.sf.net
-  Hostname 10.58.${sb_host}.${sb}
-  Port 17
-  IdentityFile ~/.ssh/allura_rsa
-
-Host svn*-$veid svn*-${veid}.sb.sf.net
-  Hostname 10.58.${sb_host}.${sb}
-  Port 16
-  IdentityFile ~/.ssh/allura_rsa
-
-Host git*-$veid git*-${veid}.sb.sf.net
-  Hostname 10.58.${sb_host}.${sb}
-  Port 23
-  IdentityFile ~/.ssh/allura_rsa
-''')
-
-LDIF_TMPL = string.Template('''
-dn: cn=$user,ou=users,dc=sf,dc=net
-changetype: modify
-add: sshPublicKey
-sshPublicKey: $pubkey
-''')
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
deleted file mode 100644
index dc6a695..0000000
--- a/scripts/prepare-allura-tickets-for-import.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env python
-#       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 itertools import tee, izip, chain
-import json
-import git
-from collections import Counter
-
-'''
-This script is for one-time conversion of Allura's own tickets from SourceForge
-host to forge-allura.apache.org hosting
-
-Change path variables here:
-'''
-
-filename = "/var/local/allura/tickets.json"  # Absolute path to exported tickets.json
-output = "/var/local/allura/updated_tickets.json"  # Absolute path to the output
-ticket_list = "/var/local/allura/ticket_ids.list"
-top_usernames = "/var/local/allura/top_usernames.list"
-gitrepository = "/var/local/allura"  # Path to allura repository
-g = git.Git(gitrepository)
-
-reviews = ['code-review', 'design-review']
-
-with open(filename, 'r') as json_file:
-    data = json.loads(json_file.read())
-
-
-def pairwise(iterable):
-    """s -> (s0,s1), (s1,s2), (s2, s3), ..."""
-    a, b = tee(iterable)
-    next(b, None)
-    return izip(a, b)
-
-
-tags = ['asf_release_1.0.0', 'asf_release_1.0.0-RC1', 'asf_release_1.0.1', 'asf_release_1.1.0', 'HEAD']
-
-tag_log = dict()
-for tag1, tag2 in pairwise(tags):
-    log = g.log('%s...%s' % (tag1, tag2), '--pretty=oneline')
-    tag_log[tag2] = log
-
-ticket_tag = dict()
-tickets = data.pop('tickets')
-for ticket in tickets:
-    for key, value in tag_log.iteritems():
-        if "[#%s]" % ticket['ticket_num'] in value:
-            ticket_tag[ticket['ticket_num']] = key
-            continue
-
-data.pop('milestones', None)
-data.pop('saved_bins', None)
-
-updated = []
-for ticket in tickets:
-    if not ticket['private'] or ticket['ticket_num'] == 6054:
-        if ticket['status'] in reviews:
-            ticket['status'] = 'review'
-
-        milestone = ticket_tag.get(ticket['ticket_num'], None)
-        if not milestone:
-            if ticket['status'] == 'closed':
-                milestone = tags[0]
-        ticket['custom_fields']['_milestone'] = milestone if milestone and milestone != 'HEAD' else 'unreleased'
-        if '_size' in ticket['custom_fields'].keys():
-            size = ticket['custom_fields']['_size']
-            if size:
-                ticket['labels'].append("sf-%d" % int(size))
-            ticket['custom_fields'].pop('_size', None)
-
-        if '_qa' in ticket['custom_fields'].keys():
-            ticket['custom_fields']['_reviewer'] = ticket['custom_fields']['_qa']
-            ticket['custom_fields'].pop('_qa', None)
-        updated.append(ticket)
-tags[-1] = 'unreleased'
-
-data['tickets'] = updated
-
-# Remove milestones from the list
-custom_fields = filter(lambda d: d.get('name') not in ['_milestone', 'name', '_size', '_qa'], data['custom_fields'])
-data['custom_fields'] = custom_fields
-
-milestones = {
-    "milestones": [
-        dict(name=milestone_name,
-             old_name=milestone_name,
-             default=False,
-             complete=False,
-             due_date="",
-             description="")
-        for milestone_name in tags
-    ],
-    "name": "_milestone",
-    "show_in_search": False,
-    "label": "Milestone",
-    "type": "milestone",
-    "options": ""
-}
-data['custom_fields'].append(milestones)
-data['custom_fields'].append({
-    "show_in_search": True,
-    "label": "Reviewer",
-    "type": "user",
-    "options": "",
-    "name": "_reviewer"
-})
-data['milestones'] = milestones
-data['saved_bins'] = []
-
-# Count top used usernames
-
-assigned_to = [ticket.get('assigned_to', None) for ticket in updated]
-reported_by = [ticket.get('reported_by', None) for ticket in updated]
-reviewed_by = [ticket['custom_fields'].get('_reviewer', None) for ticket in updated]
-
-posts = [ticket['discussion_thread']['posts'] for ticket in updated]
-
-post_authors = [post.get('author', None) for post in list(chain(*posts))]
-
-usernames = filter(lambda x: bool(x), chain(assigned_to, reported_by, reviewed_by, post_authors))
-
-top_users = Counter(usernames).most_common(50)
-
-with open(output, 'w') as outfile:
-    json.dump(data, outfile, indent=2)
-
-with open(ticket_list, 'w') as outfile:
-    outfile.write('\n'.join(sorted([str(ticket['ticket_num']) for ticket in updated])))
-
-with open(top_usernames, 'w') as outfile:
-    lines = ["%s - %s" % (username, frequency) for username, frequency in top_users]
-    outfile.write('\n'.join(lines))
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/recover-user-databases.py
----------------------------------------------------------------------
diff --git a/scripts/recover-user-databases.py b/scripts/recover-user-databases.py
deleted file mode 100644
index 5abf6f3..0000000
--- a/scripts/recover-user-databases.py
+++ /dev/null
@@ -1,72 +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 ming.orm import session
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-IGNORED_COLLECTIONS = [
-    '_flyway_migration_info',
-    'user',
-    'config',
-    'system.indexes']
-
-
-def main():
-    conn = M.session.main_doc_session.bind.conn
-    n = M.Neighborhood.query.get(url_prefix='/u/')
-    for p in M.Project.query.find(dict(neighborhood_id=n._id)):
-        if not p.database_configured:
-            continue
-        if not p.shortname.startswith('u/'):
-            continue
-        log.info('Checking to see if %s is configured...', p.database)
-        db = conn[p.database]
-        if is_unconfigured(db):
-            if sys.argv[-1] == 'test':
-                log.info('... it is not, so I would drop it.')
-                continue
-            log.info('... it is not, so dropping it.')
-            conn.drop_database(p.database)
-            p.database_configured = False
-            session(p).flush()
-        else:
-            log.info('... it is.')
-
-
-def is_unconfigured(db):
-    # Check for data in collections other than those we pre-fill with data
-    for collection_name in db.collection_names():
-        if collection_name in IGNORED_COLLECTIONS:
-            continue
-        collection = db[collection_name]
-        if collection.count():
-            log.info('...%s has data', collection_name)
-            return False
-    # DB is configured if it has more than profile/admin/search tools installed
-    if db.config.count() != 3:
-        log.info('...has %d tools', db.config.count())
-        return False
-    return True
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/setup-scm-server.py
----------------------------------------------------------------------
diff --git a/scripts/setup-scm-server.py b/scripts/setup-scm-server.py
deleted file mode 100644
index 050122c..0000000
--- a/scripts/setup-scm-server.py
+++ /dev/null
@@ -1,127 +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 os
-import string
-from tempfile import mkstemp
-from ConfigParser import ConfigParser, NoOptionError
-
-config = ConfigParser()
-
-
-def main():
-    config.read('.setup-scm-cache')
-    if not config.has_section('scm'):
-        config.add_section('scm')
-    domain = get_value('domain', 'dc=example,dc=com')
-    if config.get('start slapd', 'y') == 'y':
-        run('service slapd start')
-    if config.get('add base ldap schemas', 'y') == 'y':
-        run('ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif')
-        run('ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif')
-        run('ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif')
-    secret = config.get('admin password', 'secret')
-    if config.get('add backend ldif', 'y') == 'y':
-        add_ldif(backend_ldif, domain=domain, secret=secret)
-    if config.get('add frontend ldif', 'y') == 'y':
-        add_ldif(frontend_ldif, domain=domain, secret=secret)
-
-
-def get_value(key, default):
-    try:
-        value = config.get('scm', key)
-    except NoOptionError:
-        value = raw_input('%s? [%s]' % key, default)
-        if not value:
-            value = default
-        config.set('scm', key, value)
-    return value
-
-
-def run(command):
-    rc = os.system(command)
-    assert rc == 0
-    return rc
-
-
-def add_ldif(template, **values):
-    fd, name = mkstemp()
-    os.write(fd, template.substitute(values))
-    os.close(fd)
-    run('ldapadd -Y EXTERNAL -H ldapi:/// -f %s' % name)
-    os.remove(name)
-
-backend_ldif = string.Template('''
-# Load dynamic backend modules
-dn: cn=module,cn=config
-objectClass: olcModuleList
-cn: module
-olcModulepath: /usr/lib/ldap
-olcModuleload: back_hdb
-
-# Database settings
-dn: olcDatabase=hdb,cn=config
-objectClass: olcDatabaseConfig
-objectClass: olcHdbConfig
-olcDatabase: {1}hdb
-olcSuffix: $domain
-olcDbDirectory: /var/lib/ldap
-olcRootDN: cn=admin,$domain
-olcRootPW: $secret
-olcDbConfig: set_cachesize 0 2097152 0
-olcDbConfig: set_lk_max_objects 1500
-olcDbConfig: set_lk_max_locks 1500
-olcDbConfig: set_lk_max_lockers 1500
-olcDbIndex: objectClass eq
-olcLastMod: TRUE
-olcDbCheckpoint: 512 30
-olcAccess: to attrs=userPassword by dn="cn=admin,$domain" write by anonymous auth by self write by * none
-olcAccess: to attrs=shadowLastChange by self write by * read
-olcAccess: to dn.base="" by * read
-olcAccess: to * by dn="cn=admin,$domain" write by * read
-
-''')
-
-frontend_ldif = string.Template('''
-# Create top-level object in domain
-dn: $domain
-objectClass: top
-objectClass: dcObject
-objectclass: organization
-o: SCM Host Organization
-dc: SCM
-description: SCM Host Server
-
-# Admin user.
-dn: cn=admin,$domain
-objectClass: simpleSecurityObject
-objectClass: organizationalRole
-cn: admin
-description: LDAP administrator
-userPassword: $secret
-
-dn: ou=people,$domain
-objectClass: organizationalUnit
-ou: people
-
-dn: ou=groups,$domain
-objectClass: organizationalUnit
-ou: groups
-''')
-
-if __name__ == '__main__':
-    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/trac_export_wiki.py
----------------------------------------------------------------------
diff --git a/scripts/trac_export_wiki.py b/scripts/trac_export_wiki.py
new file mode 100755
index 0000000..025d3ca
--- /dev/null
+++ b/scripts/trac_export_wiki.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+#       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
+from optparse import OptionParser
+
+from tracwikiimporter.scripts.wiki_from_trac.extractors import WikiExporter
+
+
+def parse_options():
+    parser = OptionParser(
+        usage='%prog <Trac URL>\n\nExport wiki pages from a trac instance')
+
+    parser.add_option('-o', '--out-file', dest='out_filename',
+                      help='Write to file (default stdout)')
+    parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+                      help='Verbose operation')
+    parser.add_option('-c', '--converter', dest='converter',
+                      default='html2text',
+                      help='Converter to use on wiki text. '
+                           'Available options: html2text (default) or regex')
+    options, args = parser.parse_args()
+    if len(args) != 1:
+        parser.error('Wrong number of arguments.')
+    converters = ['html2text', 'regex']
+    if options.converter not in converters:
+        parser.error('Wrong converter. Available options: ' +
+                     ', '.join(converters))
+    return options, args
+
+
+if __name__ == '__main__':
+    options, args = parse_options()
+    exporter = WikiExporter(args[0], options)
+
+    out = sys.stdout
+    if options.out_filename:
+        out = open(options.out_filename, 'w')
+
+    exporter.export(out)

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/trac_import.py
----------------------------------------------------------------------
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
new file mode 100644
index 0000000..d4e51fd
--- /dev/null
+++ b/scripts/trac_import.py
@@ -0,0 +1,119 @@
+#       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 json
+from optparse import OptionParser
+
+from allura.lib.import_api import AlluraImportApiClient
+from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki
+
+
+def main():
+    optparser, options, args = parse_options()
+
+    import_options = {}
+    for s in options.import_opts:
+        k, v = s.split('=', 1)
+        if v == 'false':
+            v = False
+        import_options[k] = v
+
+    user_map = {}
+    if options.user_map_file:
+        f = open(options.user_map_file)
+        try:
+            user_map = json.load(f)
+            if type(user_map) is not type({}):
+                raise ValueError
+            for k, v in user_map.iteritems():
+                print k, v
+                if not isinstance(k, basestring) or not isinstance(v, basestring):
+                    raise ValueError
+        except ValueError:
+            optparser.error(
+                '--user-map should specify JSON file with format {"original_user": "sf_user", ...}')
+        finally:
+            f.close()
+
+    import_options['user_map'] = user_map
+
+    cli = AlluraImportApiClient(options.base_url, options.token, options.verbose)
+    doc_txt = open(args[0]).read()
+
+    if options.forum:
+        import_forum(cli, options.project, options.forum, user_map, doc_txt,
+                     validate=options.validate, neighborhood=options.neighborhood)
+    elif options.wiki:
+        import_wiki(cli, options.project, options.wiki, options, doc_txt)
+
+
+
+def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
+        neighborhood='p'):
+    url = '/rest/{neighborhood}/{project}/{tool}'.format(
+            neighborhood=neighborhood,
+            project=project,
+            tool=tool,
+            )
+    if validate:
+        url += '/validate_import'
+        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+    else:
+        url += '/perform_import'
+        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+
+
+def parse_options():
+    optparser = OptionParser(usage='''%prog [options] <JSON dump>
+
+Import project data dump in JSON format into an Allura project.''')
+    optparser.add_option('-t', '--token', dest='token',
+                         help='OAuth bearer token (generate at /auth/oauth/)')
+    optparser.add_option('-p', '--project', dest='project',
+                         help='Project to import to')
+    optparser.add_option('-n', '--neighborhood', dest='neighborhood',
+                         help="URL prefix of destination neighborhood (default is 'p')",
+                         default='p')
+    optparser.add_option('-f', '--forum', dest='forum',
+                         help='Forum tool to import to')
+    optparser.add_option('-w', '--wiki', dest='wiki',
+                         help='Wiki tool to import to')
+    optparser.add_option('-u', '--base-url', dest='base_url',
+                         default='https://sourceforge.net', help='Base Allura URL (%default)')
+    optparser.add_option('-o', dest='import_opts',
+                         default=[], action='append', help='Specify import option(s)', metavar='opt=val')
+    optparser.add_option('--user-map', dest='user_map_file',
+                         help='Map original users to SF.net users', metavar='JSON_FILE')
+    optparser.add_option('--validate', dest='validate',
+                         action='store_true', help='Validate import data')
+    optparser.add_option('-v', '--verbose', dest='verbose',
+                         action='store_true', help='Verbose operation')
+    optparser.add_option('-c', '--continue', dest='cont',
+                         action='store_true', help='Continue import into existing tracker')
+    options, args = optparser.parse_args()
+    if len(args) != 1:
+        optparser.error("Wrong number of arguments")
+    if not options.token:
+        optparser.error("OAuth bearer token is required")
+    if not options.project:
+        optparser.error("Target project is required")
+    options.neighborhood = options.neighborhood.strip('/')
+    return optparser, options, args
+
+
+if __name__ == '__main__':
+    main()

http://git-wip-us.apache.org/repos/asf/allura/blob/3189602c/scripts/wiki-export.py
----------------------------------------------------------------------
diff --git a/scripts/wiki-export.py b/scripts/wiki-export.py
deleted file mode 100755
index 025d3ca..0000000
--- a/scripts/wiki-export.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-
-#       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
-from optparse import OptionParser
-
-from tracwikiimporter.scripts.wiki_from_trac.extractors import WikiExporter
-
-
-def parse_options():
-    parser = OptionParser(
-        usage='%prog <Trac URL>\n\nExport wiki pages from a trac instance')
-
-    parser.add_option('-o', '--out-file', dest='out_filename',
-                      help='Write to file (default stdout)')
-    parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
-                      help='Verbose operation')
-    parser.add_option('-c', '--converter', dest='converter',
-                      default='html2text',
-                      help='Converter to use on wiki text. '
-                           'Available options: html2text (default) or regex')
-    options, args = parser.parse_args()
-    if len(args) != 1:
-        parser.error('Wrong number of arguments.')
-    converters = ['html2text', 'regex']
-    if options.converter not in converters:
-        parser.error('Wrong converter. Available options: ' +
-                     ', '.join(converters))
-    return options, args
-
-
-if __name__ == '__main__':
-    options, args = parse_options()
-    exporter = WikiExporter(args[0], options)
-
-    out = sys.stdout
-    if options.out_filename:
-        out = open(options.out_filename, 'w')
-
-    exporter.export(out)