Fix server exit hang on MacOS, cleanup, include directories in zips, natural sort.

This commit is contained in:
Leo Vasanko 2023-11-07 16:54:46 -08:00
parent 63f6008a0a
commit 37167a41a6
6 changed files with 37 additions and 33 deletions

View File

@ -55,11 +55,16 @@ async function sendChunk(file: File, start: number, end: number) {
}
}
async function uploadFileChangeHandler(event: Event) {
async function uploadHandler(event: Event) {
const target = event.target as HTMLInputElement
const chunkSize = 1 << 20
if (target && target.files && target.files.length > 0) {
const file = target.files[0]
if (!target?.files?.length) {
documentStore.error = 'No files selected'
return
}
for (const idx in target.files) {
const file = target.files[idx]
console.log('Uploading', file)
const numChunks = Math.ceil(file.size / chunkSize)
const document = documentStore.pushUploadingDocuments(file.name)
open('bottomRight')
@ -78,14 +83,14 @@ async function uploadFileChangeHandler(event: Event) {
<template>
<input
ref="fileUploadButton"
@change="uploadFileChangeHandler"
@change="uploadHandler"
class="upload-input"
type="file"
multiple
/>
<input
ref="folderUploadButton"
@change="uploadFileChangeHandler"
@change="uploadHandler"
class="upload-input"
type="file"
webkitdirectory

View File

@ -1,16 +1,22 @@
import asyncio
import datetime
import mimetypes
from collections import deque
from concurrent.futures import ThreadPoolExecutor
from importlib.resources import files
from pathlib import Path
from stat import S_IFDIR, S_IFREG
from urllib.parse import unquote
from wsgiref.handlers import format_date_time
import brotli
import sanic.helpers
from blake3 import blake3
from natsort import natsorted, ns
from sanic import Blueprint, Sanic, empty, raw
from sanic.exceptions import Forbidden, NotFound
from sanic.log import logging
from stream_zip import ZIP_AUTO, stream_zip
from cista import auth, config, session, watching
from cista.api import bp
@ -168,14 +174,6 @@ async def wwwroot(req, path=""):
return raw(data, headers=headers)
import datetime
from collections import deque
from pathlib import Path
from stat import S_IFREG
from stream_zip import ZIP_AUTO, stream_zip
@app.get("/zip/<keys>/<zipfile:ext=zip>")
async def zip_download(req, keys, zipfile, ext):
"""Download a zip archive of the given keys"""
@ -191,16 +189,12 @@ async def zip_download(req, keys, zipfile, ext):
if relpar or attr.key in wanted:
rel = [*relpar, name] if relpar else [name]
wanted.discard(attr.key)
if isinstance(attr, DirEntry):
isdir = isinstance(attr, DirEntry)
if isdir:
q.append((loc, rel, attr.dir))
elif rel:
if rel:
files.append(
(
"/".join(rel),
Path(watching.rootpath.joinpath(*loc)),
attr.mtime,
attr.size,
)
("/".join(rel), Path(watching.rootpath.joinpath(*loc)))
)
if not files:
@ -211,14 +205,17 @@ async def zip_download(req, keys, zipfile, ext):
if wanted:
raise NotFound("Files not found", context={"missing": wanted})
for rel, p, mtime, size in files:
if not p.is_file():
raise NotFound(f"File not found {rel}")
files = natsorted(files, key=lambda f: f[0], alg=ns.IGNORECASE)
def local_files(files):
for rel, p, mtime, size in files:
modified = datetime.datetime.fromtimestamp(mtime, datetime.UTC)
yield rel, modified, S_IFREG | 0o644, ZIP_AUTO(size), contents(p)
for rel, p in files:
s = p.stat()
size = s.st_size
modified = datetime.datetime.fromtimestamp(s.st_mtime, datetime.UTC)
if p.is_dir():
yield rel, modified, S_IFDIR | 0o755, ZIP_AUTO(size), b""
else:
yield rel, modified, S_IFREG | 0o644, ZIP_AUTO(size), contents(p)
def contents(name):
with name.open("rb") as f:

View File

@ -71,7 +71,7 @@ def verify(request, *, privileged=False):
raise Forbidden("Access Forbidden: Only for privileged users")
elif config.config.public or request.ctx.user:
return
raise Unauthorized("Login required", "cookie", context={"redirect": "/login"})
raise Unauthorized("Login required", "cookie")
bp = Blueprint("auth")

View File

@ -30,7 +30,10 @@ def run(*, dev=False):
reload_dir={confdir, wwwroot},
access_log=True,
) # type: ignore
Sanic.serve()
if dev:
Sanic.serve()
else:
Sanic.serve_single()
def check_cert(certdir, domain):

View File

@ -40,7 +40,6 @@ def watcher_thread(loop):
with tree_lock:
# Initialize the tree from filesystem
tree[""] = walk(rootpath)
print(" ".join(tree[""].dir.keys()))
msg = format_tree()
if msg != old:
asyncio.run_coroutine_threadsafe(broadcast(msg), loop)
@ -78,13 +77,12 @@ def watcher_thread(loop):
def watcher_thread_poll(loop):
global disk_usage, rootpath
while True:
while not quit:
rootpath = config.config.path
old = format_tree() if tree[""] else None
with tree_lock:
# Initialize the tree from filesystem
tree[""] = walk(rootpath)
print(" ".join(tree[""].dir.keys()))
msg = format_tree()
if msg != old:
asyncio.run_coroutine_threadsafe(broadcast(msg), loop)

View File

@ -20,11 +20,12 @@ dependencies = [
"docopt",
"inotify",
"msgspec",
"natsort",
"pathvalidate",
"pyjwt",
"sanic",
"tomli_w",
"stream-zip",
"tomli_w",
]
[project.urls]