aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/tutorial.txt26
-rw-r--r--libbe/command/help.py29
-rw-r--r--libbe/command/serve_storage.py328
-rw-r--r--libbe/storage/__init__.py7
-rw-r--r--libbe/storage/http.py368
-rw-r--r--libbe/ui/command_line.py3
-rw-r--r--libbe/util/wsgi.py7
-rw-r--r--misc/completion/be.zsh16
-rwxr-xr-xtest_upgrade.py33
9 files changed, 7 insertions, 810 deletions
diff --git a/doc/tutorial.txt b/doc/tutorial.txt
index 443ac2a..3a1b8e8 100644
--- a/doc/tutorial.txt
+++ b/doc/tutorial.txt
@@ -372,33 +372,13 @@ BE over HTTP
------------
Besides using BE to work directly with local VCS-based repositories,
-you can use::
-
- $ be serve-storage
-
-To serve a repository over HTTP. For example::
-
- $ be serve-storage > server.log 2>&1 &
- $ be --repo http://localhost:8000 list
-
-Of course, be careful about serving over insecure networks, since
-malicous users could fill your disk with endless bugs, etc. You can
-disabled write access by using the ``--read-only`` option, which would
-make serving on a public network safer.
-
-Serving the storage interface is flexible, but it can be inefficient.
-For example, a call to ``be list`` against a remote backend requires
-all bug information to be transfered over the wire. As a faster
-alternative, you may want to serve your repository at the command
-level::
+you can serve your repository over HTTP at the command level::
$ be serve-commands > server.log 2>&1 &
$ be --server http://localhost:8000 list
-Take a look at the server logs to get a feel for the bandwidth you're
-saving! Serving commands over insecure networks is at least as
-dangerous as serving storage. Take appropriate precautions for your
-network.
+Serving commands over insecure networks can be dangerous. Take
+appropriate precautions for your network.
Driving the VCS through BE
--------------------------
diff --git a/libbe/command/help.py b/libbe/command/help.py
index 6a04117..3af7769 100644
--- a/libbe/command/help.py
+++ b/libbe/command/help.py
@@ -33,28 +33,6 @@ may or may not be versioned. If you're using BE to track bugs in your
local software, you'll probably be using an on-disk storage based on
the VCS you use to version the storage. See `be help init` for
details about automatic VCS-detection.
-
-While most users will be using local storage, BE also supports remote
-storage servers. This allows projects to publish their local
-repository in a way that's directly accessible to remote users. The
-remote users can then use a local BE client to interact with the
-remote repository, without having to create a local copy of the
-repository. The remote server will be running something like:
-
- $ be serve-storage --host 123.123.123.123 --port 54321
-
-And the local client can run:
-
- $ be --repo http://123.123.123.123:54321 list
-
-or whichever command they like.
-
-Because the storage server serves repositories at the `Storage` level,
-it can be inefficient. For example, `be list` will have to transfer
-the data for all the bugs in a repository over the wire. The storage
-server can also be harder to lock down, because users with write
-access can potentially store data that cannot be parsed by BE. For a
-more efficient server, see `be serve-commands`.
""",
##
'server': """A server for remote BE command execution
@@ -64,9 +42,7 @@ particular project is to clone the project repository. They can then
use their local BE client to browse the repository and make changes,
before pushing their changes back upstream. For the average user
seeking to file a bug or comment, this can be too much work. One way
-to simplify the process is to use a storage server (see `be help
-repo`), but this is not always ideal. A more robust approach is to
-use a command server.
+to simplify the process is to use a command server.
The remote server will be running something like:
@@ -79,8 +55,7 @@ And the local client can run:
or whichever command they like. The command line arguments are parsed
locally, and then POSTed to the command server, where the command is
executed. The output of the command is returned to the client for
-display. This requires much less traffic over the wire than running
-the same command via a storage server.
+display.
""",
}
diff --git a/libbe/command/serve_storage.py b/libbe/command/serve_storage.py
deleted file mode 100644
index 1d8d0dd..0000000
--- a/libbe/command/serve_storage.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# Copyright (C) 2010-2012 Chris Ball <cjb@laptop.org>
-# W. Trevor King <wking@tremily.us>
-#
-# This file is part of Bugs Everywhere.
-#
-# Bugs Everywhere is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 2 of the License, or (at your option) any
-# later version.
-#
-# Bugs Everywhere is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Bugs Everywhere. If not, see <http://www.gnu.org/licenses/>.
-
-"""Define the :py:class:`Serve` serving BE Storage over HTTP.
-
-See Also
---------
-:py:mod:`libbe.storage.http` : the associated client
-"""
-
-import logging
-import os.path
-
-import libbe
-import libbe.command
-import libbe.command.util
-import libbe.util.http
-import libbe.util.subproc
-import libbe.util.wsgi
-import libbe.version
-
-if libbe.TESTING:
- import copy
- import doctest
- import StringIO
- import sys
- import unittest
- import wsgiref.validate
- try:
- import cherrypy.test.webtest
- cherrypy_test_webtest = True
- except ImportError:
- cherrypy_test_webtest = None
-
- import libbe.bugdir
- import libbe.util.wsgi
-
-
-class ServerApp (libbe.util.wsgi.WSGI_AppObject,
- libbe.util.wsgi.WSGI_DataObject):
- """WSGI server for a BE Storage instance over HTTP.
-
- RESTful_ WSGI request handler for serving the
- libbe.storage.http.HTTP backend with GET, POST, and HEAD commands.
- For more information on authentication and REST, see John
- Calcote's `Open Sourcery article`_
-
- .. _RESTful: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
- .. _Open Sourcery article: http://jcalcote.wordpress.com/2009/08/10/restful-authentication/
-
- This serves files from a connected storage instance, usually
- a VCS-based repository located on the local machine.
-
- Notes
- -----
-
- The GET and HEAD requests are identical except that the HEAD
- request omits the actual content of the file.
- """
- server_version = 'BE-storage-server/' + libbe.version.version()
-
- def __init__(self, storage=None, notify=False, **kwargs):
- super(ServerApp, self).__init__(
- urls=[
- (r'^add/?', self.add),
- (r'^exists/?', self.exists),
- (r'^remove/?', self.remove),
- (r'^ancestors/?', self.ancestors),
- (r'^children/?', self.children),
- (r'^get/(.+)', self.get),
- (r'^set/(.+)', self.set),
- (r'^commit/?', self.commit),
- (r'^revision-id/?', self.revision_id),
- (r'^changed/?', self.changed),
- (r'^version/?', self.version),
- ],
- **kwargs)
- self.storage = storage
- self.notify = notify
-
- # handlers
- def add(self, environ, start_response):
- data = self.post_data(environ)
- source = 'post'
- id = self.data_get_id(data, source=source)
- parent = self.data_get_string(
- data, 'parent', default=None, source=source)
- directory = self.data_get_boolean(
- data, 'directory', default=False, source=source)
- self.storage.add(id, parent=parent, directory=directory)
- if self.notify:
- self._notify(environ, 'add', id,
- [('parent', parent), ('directory', directory)])
- return self.ok_response(environ, start_response, None)
-
- def exists(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- id = self.data_get_id(data, source=source)
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- content = str(self.storage.exists(id, revision))
- return self.ok_response(environ, start_response, content)
-
- def remove(self, environ, start_response):
- data = self.post_data(environ)
- source = 'post'
- id = self.data_get_id(data, source=source)
- recursive = self.data_get_boolean(
- data, 'recursive', default=False, source=source)
- if recursive == True:
- self.storage.recursive_remove(id)
- else:
- self.storage.remove(id)
- if self.notify:
- self._notify(environ, 'remove', id, [('recursive', recursive)])
- return self.ok_response(environ, start_response, None)
-
- def ancestors(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- id = self.data_get_id(data, source=source)
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- content = '\n'.join(self.storage.ancestors(id, revision))+'\n'
- return self.ok_response(environ, start_response, content)
-
- def children(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- id = self.data_get_id(data, default=None, source=source)
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- content = '\n'.join(self.storage.children(id, revision))
- return self.ok_response(environ, start_response, content)
-
- def get(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- try:
- id = environ['be-server.url_args'][0]
- except:
- raise libbe.util.wsgi.HandlerError(404, 'Not Found')
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- content = self.storage.get(id, revision=revision)
- be_version = self.storage.storage_version(revision)
- return self.ok_response(environ, start_response, content,
- headers=[('X-BE-Version', be_version)])
-
- def set(self, environ, start_response):
- data = self.post_data(environ)
- try:
- id = environ['be-server.url_args'][0]
- except:
- raise libbe.util.wsgi.HandlerError(404, 'Not Found')
- if not 'value' in data:
- raise libbe.util.wsgi.HandlerError(406, 'Missing query key value')
- value = data['value']
- self.storage.set(id, value)
- if self.notify:
- self._notify(environ, 'set', id, [('value', value)])
- return self.ok_response(environ, start_response, None)
-
- def commit(self, environ, start_response):
- data = self.post_data(environ)
- if not 'summary' in data:
- raise libbe.util.wsgi.HandlerError(
- 406, 'Missing query key summary')
- summary = data['summary']
- if not 'body' in data or data['body'] == 'None':
- data['body'] = None
- body = data['body']
- if not 'allow_empty' in data \
- or data['allow_empty'] == 'True':
- allow_empty = True
- else:
- allow_empty = False
- try:
- revision = self.storage.commit(summary, body, allow_empty)
- except libbe.storage.EmptyCommit, e:
- raise libbe.util.wsgi.HandlerError(
- libbe.util.http.HTTP_USER_ERROR, 'EmptyCommit')
- if self.notify:
- self._notify(environ, 'commit', id,
- [('allow_empty', allow_empty), ('summary', summary),
- ('body', body)])
- return self.ok_response(environ, start_response, revision)
-
- def revision_id(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- index = int(self.data_get_string(
- data, 'index', default=libbe.util.wsgi.HandlerError,
- source=source))
- content = self.storage.revision_id(index)
- return self.ok_response(environ, start_response, content)
-
- def changed(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- add,mod,rem = self.storage.changed(revision)
- content = '\n\n'.join(['\n'.join(p) for p in (add,mod,rem)])
- return self.ok_response(environ, start_response, content)
-
- def version(self, environ, start_response):
- data = self.query_data(environ)
- source = 'query'
- revision = self.data_get_string(
- data, 'revision', default=None, source=source)
- content = self.storage.storage_version(revision)
- return self.ok_response(environ, start_response, content)
-
- def _notify(self, environ, command, id, params):
- message = self._format_notification(environ, command, id, params)
- self._submit_notification(message)
-
- def _format_notification(self, environ, command, id, params):
- key_length = len('command')
- for key,value in params:
- if len(key) > key_length and '\n' not in str(value):
- key_length = len(key)
- key_length += 1
- lines = []
- multi_line_params = []
- for key,value in [('address', environ.get('REMOTE_ADDR', '-')),
- ('command', command), ('id', id)]+params:
- v = str(value)
- if '\n' in v:
- multi_line_params.append((key,v))
- continue
- lines.append('%*.*s %s' % (key_length, key_length, key+':', v))
- lines.append('')
- for key,value in multi_line_params:
- lines.extend(['=== START %s ===' % key, v,
- '=== STOP %s ===' % key, ''])
- lines.append('')
- return '\n'.join(lines)
-
- def _submit_notification(self, message):
- libbe.util.subproc.invoke(self.notify, stdin=message, shell=True)
-
-
-class ServeStorage (libbe.util.wsgi.ServerCommand):
- """Serve bug directory storage over HTTP.
-
- This allows you to run local `be` commands interfacing with remote
- data, transmitting file reads/writes/etc. over the network.
-
- :py:class:`~libbe.command.base.Command` wrapper around
- :py:class:`ServerApp`.
- """
-
- name = 'serve-storage'
-
- def _get_app(self, logger, storage, **kwargs):
- return ServerApp(
- logger=logger, storage=storage, notify=kwargs.get('notify', False))
-
- def _long_help(self):
- return """
-Example usage::
-
- $ be serve-storage
-
-And in another terminal (or after backgrounding the server)::
-
- $ be --repo http://localhost:8000/ list
-
-If you bind your server to a public interface, take a look at the
-``--read-only`` option so other people can't mess with your repository.
-"""
-
-
-# alias for libbe.command.base.get_command_class()
-Serve_storage = ServeStorage
-
-
-if libbe.TESTING:
- class ServerAppTestCase (libbe.util.wsgi.WSGITestCase):
- def setUp(self):
- super(ServerAppTestCase, self).setUp()
- self.bd = libbe.bugdir.SimpleBugDir(memory=False)
- self.app = ServerApp(self.bd.storage, logger=self.logger)
-
- def tearDown(self):
- self.bd.cleanup()
- super(ServerAppTestCase, self).tearDown()
-
- def test_add_get(self):
- try:
- self.getURL(self.app, '/add/', method='GET')
- except libbe.util.wsgi.HandlerError as e:
- self.failUnless(e.code == 404, e)
- else:
- self.fail('GET /add/ did not raise 404')
-
- def test_add_post(self):
- self.getURL(self.app, '/add/', method='POST',
- data_dict={'id':'123456', 'parent':'abc123',
- 'directory':'True'})
- self.failUnless(self.status == '200 OK', self.status)
- self.failUnless(self.response_headers == [],
- self.response_headers)
- self.failUnless(self.exc_info is None, self.exc_info)
- # Note: other methods tested in libbe.storage.http
-
- # TODO: integration tests on Serve?
-
- unitsuite =unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
- suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])
diff --git a/libbe/storage/__init__.py b/libbe/storage/__init__.py
index ccadb9c..01885e9 100644
--- a/libbe/storage/__init__.py
+++ b/libbe/storage/__init__.py
@@ -23,7 +23,6 @@ data.
Also define assorted implementations for the Storage classes:
* :py:mod:`libbe.storage.vcs`
-* :py:mod:`libbe.storage.http`
Also define an assortment of storage-related tools and utilities:
@@ -53,10 +52,6 @@ STORAGE_VERSIONS = ['Bugs Everywhere Tree 1 0',
# the current version
STORAGE_VERSION = STORAGE_VERSIONS[-1]
-def get_http_storage(location):
- import http
- return http.HTTP(location)
-
def get_vcs_storage(location):
import vcs
s = vcs.detect_vcs(location)
@@ -68,7 +63,7 @@ def get_storage(location):
Return a Storage instance from a repo location string.
"""
if location.startswith('http://') or location.startswith('https://'):
- return get_http_storage(location)
+ raise ConnectionError('HTTP URLs are no longer supported')
return get_vcs_storage(location)
__all__ = [ConnectionError, InvalidStorageVersion, InvalidID,
diff --git a/libbe/storage/http.py b/libbe/storage/http.py
deleted file mode 100644
index 030349d..0000000
--- a/libbe/storage/http.py
+++ /dev/null
@@ -1,368 +0,0 @@
-# Copyright (C) 2010-2012 Chris Ball <cjb@laptop.org>
-# W. Trevor King <wking@tremily.us>
-#
-# This file is part of Bugs Everywhere.
-#
-# Bugs Everywhere is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 2 of the License, or (at your option) any
-# later version.
-#
-# Bugs Everywhere is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Bugs Everywhere. If not, see <http://www.gnu.org/licenses/>.
-
-"""Define an HTTP-based :py:class:`~libbe.storage.base.VersionedStorage`
-implementation.
-
-See Also
---------
-:py:mod:`libbe.command.serve_storage` : the associated server
-"""
-
-from __future__ import absolute_import
-import sys
-import urllib
-import urlparse
-
-import libbe
-import libbe.version
-import libbe.util.http
-from libbe.util.http import HTTP_VALID, HTTP_USER_ERROR
-from . import base
-
-from libbe import TESTING
-
-if TESTING == True:
- import copy
- import doctest
- import StringIO
- import unittest
-
- import libbe.bugdir
- import libbe.command.serve_storage
- import libbe.util.http
- import libbe.util.wsgi
-
-
-class HTTP (base.VersionedStorage):
- """:py:class:`~libbe.storage.base.VersionedStorage` implementation over
- HTTP.
-
- Uses GET to retrieve information and POST to set information.
- """
- name = 'HTTP'
- user_agent = 'BE-HTTP-Storage'
-
- def __init__(self, repo, *args, **kwargs):
- repo,self.uname,self.password = self.parse_repo(repo)
- base.VersionedStorage.__init__(self, repo, *args, **kwargs)
-
- def parse_repo(self, repo):
- """Grab username and password (if any) from the repo URL.
-
- Examples
- --------
-
- >>> s = HTTP('http://host.com/path/to/repo')
- >>> s.repo
- 'http://host.com/path/to/repo'
- >>> s.uname == None
- True
- >>> s.password == None
- True
- >>> s.parse_repo('http://joe:secret@host.com/path/to/repo')
- ('http://host.com/path/to/repo', 'joe', 'secret')
- """
- scheme,netloc,path,params,query,fragment = urlparse.urlparse(repo)
- parts = netloc.split('@', 1)
- if len(parts) == 2:
- uname,password = parts[0].split(':')
- repo = urlparse.urlunparse(
- (scheme, parts[1], path, params, query, fragment))
- else:
- uname,password = (None, None)
- return (repo, uname, password)
-
- def get_post_url(self, url, get=True, data_dict=None, headers=[]):
- if self.uname != None and self.password != None:
- headers.append(('Authorization','Basic %s' % \
- ('%s:%s' % (self.uname, self.password)).encode('base64')))
- return libbe.util.http.get_post_url(
- url, get, data_dict=data_dict, headers=headers,
- agent=self.user_agent)
-
- def storage_version(self, revision=None):
- """Return the storage format for this backend."""
- return libbe.storage.STORAGE_VERSION
-
- def _init(self):
- """Create a new storage repository."""
- raise base.NotSupported(
- 'init', 'Cannot initialize this repository format.')
-
- def _destroy(self):
- """Remove the storage repository."""
- raise base.NotSupported(
- 'destroy', 'Cannot destroy this repository format.')
-
- def _connect(self):
- self.check_storage_version()
-
- def _disconnect(self):
- pass
-
- def _add(self, id, parent=None, directory=False):
- url = urlparse.urljoin(self.repo, 'add')
- page,final_url,info = self.get_post_url(
- url, get=False,
- data_dict={'id':id, 'parent':parent, 'directory':directory})
-
- def _exists(self, id, revision=None):
- url = urlparse.urljoin(self.repo, 'exists')
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'id':id, 'revision':revision})
- if page == 'True':
- return True
- return False
-
- def _remove(self, id):
- url = urlparse.urljoin(self.repo, 'remove')
- page,final_url,info = self.get_post_url(
- url, get=False,
- data_dict={'id':id, 'recursive':False})
-
- def _recursive_remove(self, id):
- url = urlparse.urljoin(self.repo, 'remove')
- page,final_url,info = self.get_post_url(
- url, get=False,
- data_dict={'id':id, 'recursive':True})
-
- def _ancestors(self, id=None, revision=None):
- url = urlparse.urljoin(self.repo, 'ancestors')
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'id':id, 'revision':revision})
- return page.strip('\n').splitlines()
-
- def _children(self, id=None, revision=None):
- url = urlparse.urljoin(self.repo, 'children')
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'id':id, 'revision':revision})
- return page.strip('\n').splitlines()
-
- def _get(self, id, default=base.InvalidObject, revision=None):
- url = urlparse.urljoin(self.repo, '/'.join(['get', id]))
- try:
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'revision':revision})
- except libbe.util.http.HTTPError, e:
- if not (hasattr(e.error, 'code') and e.error.code in HTTP_VALID):
- raise
- elif default == base.InvalidObject:
- raise base.InvalidID(id)
- return default
- version = info['X-BE-Version']
- if version != libbe.storage.STORAGE_VERSION:
- raise base.InvalidStorageVersion(
- version, libbe.storage.STORAGE_VERSION)
- return page
-
- def _set(self, id, value):
- url = urlparse.urljoin(self.repo, '/'.join(['set', id]))
- try:
- page,final_url,info = self.get_post_url(
- url, get=False,
- data_dict={'value':value})
- except libbe.util.http.HTTPError, e:
- if not (hasattr(e.error, 'code') and e.error.code in HTTP_VALID):
- raise
- if e.error.code == HTTP_USER_ERROR \
- and not 'InvalidID' in str(e.error):
- raise base.InvalidDirectory(
- 'Directory %s cannot have data' % id)
- raise base.InvalidID(id)
-
- def _commit(self, summary, body=None, allow_empty=False):
- url = urlparse.urljoin(self.repo, 'commit')
- try:
- page,final_url,info = self.get_post_url(
- url, get=False,
- data_dict={'summary':summary, 'body':body,
- 'allow_empty':allow_empty})
- except libbe.util.http.HTTPError, e:
- if not (hasattr(e.error, 'code') and e.error.code in HTTP_VALID):
- raise
- if e.error.code == HTTP_USER_ERROR:
- raise base.EmptyCommit
- raise base.InvalidID(id)
- return page.rstrip('\n')
-
- def revision_id(self, index=None):
- """Return the name of the <index>th revision.
-
- The choice of which branch to follow when crossing
- branches/merges is not defined. Revision indices start at 1;
- ID 0 is the blank repository.
-
- Return None if index==None.
-
- Raises
- ------
- InvalidRevision
- If the specified revision does not exist.
- """
- if index == None:
- return None
- try:
- if int(index) != index:
- raise base.InvalidRevision(index)
- except ValueError:
- raise base.InvalidRevision(index)
- url = urlparse.urljoin(self.repo, 'revision-id')
- try:
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'index':index})
- except libbe.util.http.HTTPError, e:
- if not (hasattr(e.error, 'code') and e.error.code in HTTP_VALID):
- raise
- if e.error.code == HTTP_USER_ERROR:
- raise base.InvalidRevision(index)
- raise base.InvalidID(id)
- return page.rstrip('\n')
-
- def changed(self, revision=None):
- url = urlparse.urljoin(self.repo, 'changed')
- page,final_url,info = self.get_post_url(
- url, get=True,
- data_dict={'revision':revision})
- lines = page.strip('\n')
- new,mod,rem = [p.splitlines() for p in page.split('\n\n')]
- return (new, mod, rem)
-
- def check_storage_version(self):
- version = self.storage_version()
- if version != libbe.storage.STORAGE_VERSION:
- raise base.InvalidStorageVersion(
- version, libbe.storage.STORAGE_VERSION)
-
- def storage_version(self, revision=None):
- url = urlparse.urljoin(self.repo, 'version')
- page,final_url,info = self.get_post_url(
- url, get=True, data_dict={'revision':revision})
- return page.rstrip('\n')
-
-if TESTING == True:
- class TestingHTTP (HTTP):
- name = 'TestingHTTP'
- def __init__(self, repo, *args, **kwargs):
- self._storage_backend = base.VersionedStorage(repo)
- app = libbe.command.serve_storage.ServerApp(
- storage=self._storage_backend)
- self.app = libbe.util.wsgi.BEExceptionApp(app=app)
- HTTP.__init__(self, repo='http://localhost:8000/', *args, **kwargs)
- self.intitialized = False
- # duplicated from libbe.util.wsgi.WSGITestCase
- self.default_environ = {
- 'REQUEST_METHOD': 'GET', # 'POST', 'HEAD'
- 'REMOTE_ADDR': '192.168.0.123',
- 'SCRIPT_NAME':'',
- 'PATH_INFO': '',
- #'QUERY_STRING':'', # may be empty or absent
- #'CONTENT_TYPE':'', # may be empty or absent
- #'CONTENT_LENGTH':'', # may be empty or absent
- 'SERVER_NAME':'example.com',
- 'SERVER_PORT':'80',
- 'SERVER_PROTOCOL':'HTTP/1.1',
- 'wsgi.version':(1,0),
- 'wsgi.url_scheme':'http',
- 'wsgi.input':StringIO.StringIO(),
- 'wsgi.errors':StringIO.StringIO(),
- 'wsgi.multithread':False,
- 'wsgi.multiprocess':False,
- 'wsgi.run_once':False,
- }
- def getURL(self, app, path='/', method='GET', data=None,
- scheme='http', environ={}):
- # duplicated from libbe.util.wsgi.WSGITestCase
- env = copy.copy(self.default_environ)
- env['PATH_INFO'] = path
- env['REQUEST_METHOD'] = method
- env['scheme'] = scheme
- if data != None:
- enc_data = urllib.urlencode(data)
- if method == 'POST':
- env['CONTENT_LENGTH'] = len(enc_data)
- env['wsgi.input'] = StringIO.StringIO(enc_data)
- else:
- assert method in ['GET', 'HEAD'], method
- env['QUERY_STRING'] = enc_data
- for key,value in environ.items():
- env[key] = value
- try:
- result = app(env, self.start_response)
- except libbe.util.wsgi.HandlerError as e:
- raise libbe.util.http.HTTPError(error=e, url=path, msg=str(e))
- return ''.join(result)
- def start_response(self, status, response_headers, exc_info=None):
- self.status = status
- self.response_headers = response_headers
- self.exc_info = exc_info
- def get_post_url(self, url, get=True, data_dict=None, headers=[]):
- if get == True:
- method = 'GET'
- else:
- method = 'POST'
- scheme,netloc,path,params,query,fragment = urlparse.urlparse(url)
- environ = {}
- for header_name,header_value in headers:
- environ['HTTP_%s' % header_name] = header_value
- output = self.getURL(
- self.app, path, method, data_dict, scheme, environ)
- if self.status != '200 OK':
- class __estr (object):
- def __init__(self, string):
- self.string = string
- self.code = int(string.split()[0])
- def __str__(self):
- return self.string
- error = __estr(self.status)
- raise libbe.util.http.HTTPError(
- error=error, url=url, msg=output)
- info = dict(self.response_headers)
- return (output, url, info)
- def _init(self):
- try:
- HTTP._init(self)
- raise AssertionError
- except base.NotSupported:
- pass
- self._storage_backend._init()
- def _destroy(self):
- try:
- HTTP._destroy(self)
- raise AssertionError
- except base.NotSupported:
- pass
- self._storage_backend._destroy()
- def _connect(self):
- self._storage_backend._connect()
- HTTP._connect(self)
- def _disconnect(self):
- HTTP._disconnect(self)
- self._storage_backend._disconnect()
-
-
- base.make_versioned_storage_testcase_subclasses(
- TestingHTTP, sys.modules[__name__])
-
- unitsuite =unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
- suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])
diff --git a/libbe/ui/command_line.py b/libbe/ui/command_line.py
index 614366d..5d4d80a 100644
--- a/libbe/ui/command_line.py
+++ b/libbe/ui/command_line.py
@@ -379,8 +379,7 @@ def main():
ui.setup_command(command)
if command.name in [
- 'new', 'comment', 'commit', 'html', 'import-xml', 'serve-storage',
- 'serve-commands']:
+ 'new', 'comment', 'commit', 'html', 'import-xml', 'serve-commands']:
paginate = 'never'
else:
paginate = 'auto'
diff --git a/libbe/util/wsgi.py b/libbe/util/wsgi.py
index 2e97941..c509a48 100644
--- a/libbe/util/wsgi.py
+++ b/libbe/util/wsgi.py
@@ -20,7 +20,6 @@
See Also
--------
-:py:mod:`libbe.command.serve_storage` and
:py:mod:`libbe.command.serve_commands`.
"""
@@ -87,12 +86,6 @@ class HandlerError (Exception):
self.headers = headers
-class Unauthenticated (HandlerError):
- def __init__(self, realm, msg='User Not Authenticated', headers=[]):
- super(Unauthenticated, self).__init__(401, msg, headers+[
- ('WWW-Authenticate','Basic realm="{}"'.format(realm))])
-
-
class Unauthorized (HandlerError):
def __init__(self, msg='User Not Authorized', headers=[]):
super(Unauthorized, self).__init__(403, msg, headers)
diff --git a/misc/completion/be.zsh b/misc/completion/be.zsh
index 36cfddc..dee8017 100644
--- a/misc/completion/be.zsh
+++ b/misc/completion/be.zsh
@@ -21,7 +21,6 @@ __be_commands () {
merge:'Merge duplicate bugs'
new:'Create a new bug'
remove:'Remove (delete) a bug and its comments'
- serve:'Serve bug directory storage over HTTP'
set:'Change bug directory settings'
severity:'Change a bug’s severity level'
show:'Show a particular bug, comment, or combination of both'
@@ -226,21 +225,6 @@ _be-remove () {
&& return 0
}
-_be-serve () {
- local curcontext="$curcontext" state line expl ret=1
-
- _arguments -C \
- '(-h --help)'{-h,--help}'[Print a help message]' \
- '--complete[Print a list of possible completions]' \
- '--port=-[Bind server to port]' \
- '--host=-[Set host string]' \
- '(-r --read-only)'{-r,--read-only}'[Disable operations that require writing]' \
- '(-n --notify)'{-n,--notify=-}'[Send notification emails for changes]' \
- '(-s --ssl)'{-s,--ssl}'[Use CherryPy to serve HTTPS (HTTP over SSL/TLS)]' \
- '(-a --auth)'{-a,--auth=-}'[Require authentication]' \
- && return 0
-}
-
_be-set () {
local curcontext="$curcontext" state line expl ret=1
diff --git a/test_upgrade.py b/test_upgrade.py
deleted file mode 100755
index 40db42a..0000000
--- a/test_upgrade.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-#
-# Test upgrade functionality by checking out revisions with the
-# various initial on-disk versions and running `be list` on them to
-# force an auto-upgrade.
-#
-# usage: test_upgrade.sh
-
-REVS='revid:wking@drexel.edu-20090831063121-85p59rpwoi1mzk3i
-revid:wking@drexel.edu-20090831171945-73z3wwt4lrm7zbmu
-revid:wking@drexel.edu-20091205224008-z4fed13sd80bj4fe
-revid:wking@drexel.edu-20091207123614-okq7i0ahciaupuy9'
-
-ROOT=$(bzr root)
-BE="$ROOT/be"
-cd "$ROOT"
-
-echo "$REVS" | while read REV; do
- TMPDIR=$(mktemp --directory --tmpdir "BE-upgrade.XXXXXXXXXX")
- REPO="$TMPDIR/repo"
- echo "Testing revision: $REV"
- echo " Test directory: $REPO"
- bzr checkout --lightweight --revision="$REV" "$ROOT" "$TMPDIR/repo"
- VERSION=$(cat "$REPO/.be/version")
- echo " Version: $VERSION"
- $BE --repo "$REPO" list > /dev/null
- RET="$?"
- rm -rf "$TMPDIR"
- if [ $RET -ne 0 ]; then
- echo "Error! ($RET)"
- exit $RET
- fi
-done