]> arthur.barton.de Git - bup.git/blobdiff - lib/cmd/web-cmd.py
ftp: fix ls arguments for python3
[bup.git] / lib / cmd / web-cmd.py
index 305eeaad50ee2801014cdfa87958189cdcf813fd..6ef2fe9578420418f90d2d078d7f309b69dc84c6 100755 (executable)
@@ -1,20 +1,33 @@
 #!/bin/sh
 """": # -*-python-*-
-bup_python="$(dirname "$0")/bup-python" || exit $?
-exec "$bup_python" "$0" ${1+"$@"}
+# https://sourceware.org/bugzilla/show_bug.cgi?id=26034
+export "BUP_ARGV_0"="$0"
+arg_i=1
+for arg in "$@"; do
+    export "BUP_ARGV_${arg_i}"="$arg"
+    shift
+    arg_i=$((arg_i + 1))
+done
+# Here to end of preamble replaced during install
+bup_python="$(dirname "$0")/../../config/bin/python" || exit $?
+exec "$bup_python" "$0"
 """
 # end of bup preamble
 
 from __future__ import absolute_import, print_function
 from collections import namedtuple
 import mimetypes, os, posixpath, signal, stat, sys, time, urllib, webbrowser
+from binascii import hexlify
 
-from bup import options, git, vfs
+sys.path[:0] = [os.path.dirname(os.path.realpath(__file__)) + '/..']
+
+from bup import compat, options, git, vfs
 from bup.helpers import (chunkyreader, debug1, format_filesize, handle_ctrl_c,
                          log, saved_errors)
 from bup.metadata import Metadata
 from bup.path import resource_path
 from bup.repo import LocalRepo
+from bup.io import path_msg
 
 try:
     from tornado import gen
@@ -40,14 +53,14 @@ def http_date_from_utc_ns(utc_ns):
 def _compute_breadcrumbs(path, show_hidden=False):
     """Returns a list of breadcrumb objects for a path."""
     breadcrumbs = []
-    breadcrumbs.append(('[root]', '/'))
-    path_parts = path.split('/')[1:-1]
-    full_path = '/'
+    breadcrumbs.append((b'[root]', b'/'))
+    path_parts = path.split(b'/')[1:-1]
+    full_path = b'/'
     for part in path_parts:
-        full_path += part + "/"
-        url_append = ""
+        full_path += part + b"/"
+        url_append = b""
         if show_hidden:
-            url_append = '?hidden=1'
+            url_append = b'?hidden=1'
         breadcrumbs.append((part, full_path+url_append))
     return breadcrumbs
 
@@ -58,9 +71,9 @@ def _contains_hidden_files(repo, dir_item):
 
     """
     for name, item in vfs.contents(repo, dir_item, want_meta=False):
-        if name in ('.', '..'):
+        if name in (b'.', b'..'):
             continue
-        if name.startswith('.'):
+        if name.startswith(b'.'):
             return True
     return False
 
@@ -68,15 +81,15 @@ def _contains_hidden_files(repo, dir_item):
 def _dir_contents(repo, resolution, show_hidden=False):
     """Yield the display information for the contents of dir_item."""
 
-    url_query = '?hidden=1' if show_hidden else ''
+    url_query = b'?hidden=1' if show_hidden else b''
 
     def display_info(name, item, resolved_item, display_name=None):
         # link should be based on fully resolved type to avoid extra
         # HTTP redirect.
+        link = tornado.escape.url_escape(name, plus=False)
         if stat.S_ISDIR(vfs.item_mode(resolved_item)):
-            link = urllib.quote(name) + '/'
-        else:
-            link = urllib.quote(name)
+            link += '/'
+        link = link.encode('ascii')
 
         size = vfs.item_size(repo, item)
         if opt.human_readable:
@@ -87,9 +100,9 @@ def _dir_contents(repo, resolution, show_hidden=False):
         if not display_name:
             mode = vfs.item_mode(item)
             if stat.S_ISDIR(mode):
-                display_name = name + '/'
+                display_name = name + b'/'
             elif stat.S_ISLNK(mode):
-                display_name = name + '@'
+                display_name = name + b'@'
             else:
                 display_name = name
 
@@ -98,15 +111,14 @@ def _dir_contents(repo, resolution, show_hidden=False):
     dir_item = resolution[-1][1]    
     for name, item in vfs.contents(repo, dir_item):
         if not show_hidden:
-            if (name not in ('.', '..')) and name.startswith('.'):
+            if (name not in (b'.', b'..')) and name.startswith(b'.'):
                 continue
-        if name == '.':
-            yield display_info(name, item, item, '.')
+        if name == b'.':
+            yield display_info(name, item, item, b'.')
             parent_item = resolution[-2][1] if len(resolution) > 1 else dir_item
-            yield display_info('..', parent_item, parent_item, '..')
+            yield display_info(b'..', parent_item, parent_item, b'..')
             continue
-        res = vfs.try_resolve(repo, name, parent=resolution, want_meta=False)
-        res_name, res_item = res[-1]
+        res_item = vfs.ensure_item_has_metadata(repo, item, include_size=True)
         yield display_info(name, item, res_item)
 
 
@@ -127,8 +139,8 @@ class BupRequestHandler(tornado.web.RequestHandler):
         return self._process_request(path)
     
     def _process_request(self, path):
-        path = urllib.unquote(path)
         print('Handling request for %s' % path)
+        sys.stdout.flush()
         # Set want_meta because dir metadata won't be fetched, and if
         # it's not a dir, then we're going to want the metadata.
         res = vfs.resolve(self.repo, path, want_meta=True)
@@ -148,9 +160,9 @@ class BupRequestHandler(tornado.web.RequestHandler):
         Return value is either a file object, or None (indicating an
         error).  In either case, the headers are sent.
         """
-        if not path.endswith('/') and len(path) > 0:
-            print('Redirecting from %s to %s' % (path, path + '/'))
-            return self.redirect(path + '/', permanent=True)
+        if not path.endswith(b'/') and len(path) > 0:
+            print('Redirecting from %s to %s' % (path_msg(path), path_msg(path + b'/')))
+            return self.redirect(path + b'/', permanent=True)
 
         hidden_arg = self.request.arguments.get('hidden', [0])[-1]
         try:
@@ -183,7 +195,7 @@ class BupRequestHandler(tornado.web.RequestHandler):
         
         self.set_header("Content-Length", str(meta.size))
         assert len(file_item.oid) == 20
-        self.set_header("Etag", file_item.oid.encode('hex'))
+        self.set_header("Etag", hexlify(file_item.oid))
         if self.request.method != 'HEAD':
             with vfs.fopen(self.repo, file_item) as f:
                 it = chunkyreader(f)
@@ -248,7 +260,7 @@ human-readable    display human readable file sizes (i.e. 3.9K, 4.7M)
 browser           show repository in default browser (incompatible with unix://)
 """
 o = options.Options(optspec)
-(opt, flags, extra) = o.parse(sys.argv[1:])
+opt, flags, extra = o.parse(compat.argv[1:])
 
 if len(extra) > 1:
     o.fatal("at most one argument expected")
@@ -276,12 +288,15 @@ git.check_repo_or_die()
 
 settings = dict(
     debug = 1,
-    template_path = resource_path('web'),
-    static_path = resource_path('web/static')
+    template_path = resource_path(b'web').decode('utf-8'),
+    static_path = resource_path(b'web/static').decode('utf-8'),
 )
 
 # Disable buffering on stdout, for debug messages
-sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+try:
+    sys.stdout._line_buffering = True
+except AttributeError:
+    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
 
 application = tornado.web.Application([
     (r"(?P<path>/.*)", BupRequestHandler, dict(repo=LocalRepo())),
@@ -291,12 +306,9 @@ http_server = HTTPServer(application)
 io_loop_pending = IOLoop.instance()
 
 if isinstance(address, InetAddress):
-    http_server.listen(address.port, address.host)
-    try:
-        sock = http_server._socket # tornado < 2.0
-    except AttributeError as e:
-        sock = http_server._sockets.values()[0]
-    print('Serving HTTP on %s:%d...' % sock.getsockname())
+    sockets = tornado.netutil.bind_sockets(address.port, address.host)
+    http_server.add_sockets(sockets)
+    print('Serving HTTP on %s:%d...' % sockets[0].getsockname())
     if opt.browser:
         browser_addr = 'http://' + address[0] + ':' + str(address[1])
         io_loop_pending.add_callback(lambda : webbrowser.open(browser_addr))