Compare commits
No commits in common. "61f9026e236d02177b67d194b7c789bbde66f593" and "e0aef077837e2648ca92bd6402d3c54334ddd0fb" have entirely different histories.
61f9026e23
...
e0aef07783
@ -1,7 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import secrets
|
import secrets
|
||||||
import sys
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
@ -91,8 +90,6 @@ def config_update(modify):
|
|||||||
return "read"
|
return "read"
|
||||||
f.write(new)
|
f.write(new)
|
||||||
f.close()
|
f.close()
|
||||||
if sys.platform == "win32":
|
|
||||||
conffile.unlink() # Windows doesn't support atomic replace
|
|
||||||
tmpname.rename(conffile) # Atomic replace
|
tmpname.rename(conffile) # Atomic replace
|
||||||
except:
|
except:
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -149,3 +149,15 @@ class Space(msgspec.Struct):
|
|||||||
free: int
|
free: int
|
||||||
usage: int
|
usage: int
|
||||||
storage: int
|
storage: int
|
||||||
|
|
||||||
|
|
||||||
|
def make_dir_data(root):
|
||||||
|
if len(root) == 3:
|
||||||
|
return FileEntry(*root)
|
||||||
|
id_, size, mtime, listing = root
|
||||||
|
converted = {}
|
||||||
|
for name, data in listing.items():
|
||||||
|
converted[name] = make_dir_data(data)
|
||||||
|
sz = sum(x.size for x in converted.values())
|
||||||
|
mt = max(x.mtime for x in converted.values())
|
||||||
|
return DirEntry(id_, sz, max(mt, mtime), converted)
|
||||||
|
@ -110,6 +110,26 @@ class State:
|
|||||||
with self.lock:
|
with self.lock:
|
||||||
del self._listing[self._slice(relpath)]
|
del self._listing[self._slice(relpath)]
|
||||||
|
|
||||||
|
def _index(self, rel: PurePosixPath):
|
||||||
|
idx = 0
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
def _dir(self, idx: int):
|
||||||
|
level = self._listing[idx].level + 1
|
||||||
|
end = len(self._listing)
|
||||||
|
idx += 1
|
||||||
|
ret = []
|
||||||
|
while idx < end and (r := self._listing[idx]).level >= level:
|
||||||
|
if r.level == level:
|
||||||
|
ret.append(idx)
|
||||||
|
return ret, idx
|
||||||
|
|
||||||
|
def update(self, rel: PurePosixPath, value: FileEntry):
|
||||||
|
begin = 0
|
||||||
|
parents = []
|
||||||
|
while self._listing[begin].level < len(rel.parts):
|
||||||
|
parents.append(begin)
|
||||||
|
|
||||||
|
|
||||||
state = State()
|
state = State()
|
||||||
rootpath: Path = None # type: ignore
|
rootpath: Path = None # type: ignore
|
||||||
@ -129,7 +149,7 @@ def watcher_thread(loop):
|
|||||||
global rootpath
|
global rootpath
|
||||||
import inotify.adapters
|
import inotify.adapters
|
||||||
|
|
||||||
while not quit:
|
while True:
|
||||||
rootpath = config.config.path
|
rootpath = config.config.path
|
||||||
i = inotify.adapters.InotifyTree(rootpath.as_posix())
|
i = inotify.adapters.InotifyTree(rootpath.as_posix())
|
||||||
# Initialize the tree from filesystem
|
# Initialize the tree from filesystem
|
||||||
@ -140,8 +160,8 @@ def watcher_thread(loop):
|
|||||||
state.root = new
|
state.root = new
|
||||||
broadcast(format_update(old, new), loop)
|
broadcast(format_update(old, new), loop)
|
||||||
|
|
||||||
# The watching is not entirely reliable, so do a full refresh every 30 seconds
|
# The watching is not entirely reliable, so do a full refresh every minute
|
||||||
refreshdl = time.monotonic() + 30.0
|
refreshdl = time.monotonic() + 60.0
|
||||||
|
|
||||||
for event in i.event_gen():
|
for event in i.event_gen():
|
||||||
if quit:
|
if quit:
|
||||||
@ -218,15 +238,11 @@ def _walk(rel: PurePosixPath, isfile: int, st: stat_result) -> list[FileEntry]:
|
|||||||
try:
|
try:
|
||||||
li = []
|
li = []
|
||||||
for f in path.iterdir():
|
for f in path.iterdir():
|
||||||
if quit:
|
|
||||||
raise SystemExit("quit")
|
|
||||||
if f.name.startswith("."):
|
if f.name.startswith("."):
|
||||||
continue # No dotfiles
|
continue # No dotfiles
|
||||||
s = f.stat()
|
s = f.stat()
|
||||||
li.append((int(not stat.S_ISDIR(s.st_mode)), f.name, s))
|
li.append((int(not stat.S_ISDIR(s.st_mode)), f.name, s))
|
||||||
for [isfile, name, s] in humansorted(li):
|
for [isfile, name, s] in humansorted(li):
|
||||||
if quit:
|
|
||||||
raise SystemExit("quit")
|
|
||||||
subtree = _walk(rel / name, isfile, s)
|
subtree = _walk(rel / name, isfile, s)
|
||||||
child = subtree[0]
|
child = subtree[0]
|
||||||
entry.mtime = max(entry.mtime, child.mtime)
|
entry.mtime = max(entry.mtime, child.mtime)
|
||||||
@ -321,7 +337,7 @@ async def abroadcast(msg):
|
|||||||
|
|
||||||
async def start(app, loop):
|
async def start(app, loop):
|
||||||
config.load_config()
|
config.load_config()
|
||||||
use_inotify = sys.platform == "linux"
|
use_inotify = False and sys.platform == "linux"
|
||||||
app.ctx.watcher = threading.Thread(
|
app.ctx.watcher = threading.Thread(
|
||||||
target=watcher_thread if use_inotify else watcher_thread_poll,
|
target=watcher_thread if use_inotify else watcher_thread_poll,
|
||||||
args=[loop],
|
args=[loop],
|
||||||
|
@ -29,7 +29,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://git.zi.fi/Vasanko/cista-storage"
|
Homepage = ""
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
cista = "cista.__main__:main"
|
cista = "cista.__main__:main"
|
||||||
@ -40,18 +40,20 @@ dev = [
|
|||||||
"ruff",
|
"ruff",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.hatchling]
|
||||||
|
# Build frontend
|
||||||
|
pre_build = "npm run build --prefix cista-front"
|
||||||
|
|
||||||
[tool.hatch.version]
|
[tool.hatch.version]
|
||||||
source = "vcs"
|
source = "vcs"
|
||||||
|
|
||||||
[tool.hatch.build]
|
[tool.hatch.build]
|
||||||
artifacts = ["cista/wwwroot"]
|
|
||||||
hooks.custom.path = "scripts/build-frontend.py"
|
|
||||||
hooks.vcs.version-file = "cista/_version.py"
|
hooks.vcs.version-file = "cista/_version.py"
|
||||||
hooks.vcs.template = """
|
hooks.vcs.template = """
|
||||||
# This file is automatically generated by hatch build.
|
# This file is automatically generated by hatch build.
|
||||||
__version__ = {version!r}
|
__version__ = {version!r}
|
||||||
"""
|
"""
|
||||||
only-packages = true
|
|
||||||
targets.sdist.include = [
|
targets.sdist.include = [
|
||||||
"/cista",
|
"/cista",
|
||||||
]
|
]
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
# noqa: INP001
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
||||||
|
|
||||||
|
|
||||||
class CustomBuildHook(BuildHookInterface):
|
|
||||||
def initialize(self, version, build_data):
|
|
||||||
super().initialize(version, build_data)
|
|
||||||
print("Building Cista frontend...")
|
|
||||||
subprocess.run("npm install --prefix frontend".split(" "), check=True) # noqa: S603
|
|
||||||
subprocess.run("npm run build --prefix frontend".split(" "), check=True) # noqa: S603
|
|
Loading…
x
Reference in New Issue
Block a user