mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 17:12:13 -06:00
more deletion progress
This commit is contained in:
parent
4339dbeb8d
commit
a4e1a3738a
|
@ -242,6 +242,7 @@ class VFS(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
fsroot, vfs_ls, vfs_virt = self.ls(rem, uname, scandir, permsets, lstat=lstat)
|
fsroot, vfs_ls, vfs_virt = self.ls(rem, uname, scandir, permsets, lstat=lstat)
|
||||||
|
dbv, vrem = self.get_dbv(rem)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
seen
|
seen
|
||||||
|
@ -259,7 +260,7 @@ class VFS(object):
|
||||||
rfiles.sort()
|
rfiles.sort()
|
||||||
rdirs.sort()
|
rdirs.sort()
|
||||||
|
|
||||||
yield rel, fsroot, rfiles, rdirs, vfs_virt
|
yield dbv, vrem, rel, fsroot, rfiles, rdirs, vfs_virt
|
||||||
|
|
||||||
for rdir, _ in rdirs:
|
for rdir, _ in rdirs:
|
||||||
if not dots and rdir.startswith("."):
|
if not dots and rdir.startswith("."):
|
||||||
|
@ -287,7 +288,7 @@ class VFS(object):
|
||||||
f2b = "{0}.hist{0}".format(os.sep)
|
f2b = "{0}.hist{0}".format(os.sep)
|
||||||
|
|
||||||
g = self.walk("", vrem, [], uname, [[True]], dots, scandir, False)
|
g = self.walk("", vrem, [], uname, [[True]], dots, scandir, False)
|
||||||
for vpath, apath, files, rd, vd in g:
|
for _, _, vpath, apath, files, rd, vd in g:
|
||||||
if flt:
|
if flt:
|
||||||
files = [x for x in files if x[0] in flt]
|
files = [x for x in files if x[0] in flt]
|
||||||
|
|
||||||
|
@ -795,7 +796,7 @@ class AuthSrv(object):
|
||||||
g = vn.walk(
|
g = vn.walk(
|
||||||
"", "", [], u, True, [[True]], not self.args.no_scandir, False
|
"", "", [], u, True, [[True]], not self.args.no_scandir, False
|
||||||
)
|
)
|
||||||
for vpath, apath, files, _, _ in g:
|
for _, _, vpath, apath, files, _, _ in g:
|
||||||
fnames = [n[0] for n in files]
|
fnames = [n[0] for n in files]
|
||||||
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
||||||
vpaths = [vtop + x for x in vpaths]
|
vpaths = [vtop + x for x in vpaths]
|
||||||
|
|
|
@ -1548,27 +1548,8 @@ class HttpCli(object):
|
||||||
if self.args.no_del:
|
if self.args.no_del:
|
||||||
raise Pebkac(403, "disabled by argv")
|
raise Pebkac(403, "disabled by argv")
|
||||||
|
|
||||||
permsets = [[True, False, False, True]]
|
x = self.conn.hsrv.broker.put(True, "up2k.handle_rm", self.uname, self.vpath)
|
||||||
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, *permsets[0])
|
self.loud_reply(x.get())
|
||||||
abspath = vn.canonical(rem)
|
|
||||||
|
|
||||||
fun = os.lstat if os.supports_follow_symlinks else os.stat
|
|
||||||
st = fun(fsenc(abspath))
|
|
||||||
if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode):
|
|
||||||
self.log("rm file " + abspath)
|
|
||||||
return
|
|
||||||
|
|
||||||
scandir = not self.args.no_scandir
|
|
||||||
g = vn.walk("", rem, [], self.uname, permsets, True, scandir, True)
|
|
||||||
for vpath, apath, files, rd, vd in g:
|
|
||||||
for fn in files:
|
|
||||||
m = "rm file {} / {}".format(apath, fn[0])
|
|
||||||
if "yt" in m:
|
|
||||||
self.log(m)
|
|
||||||
|
|
||||||
# build list of folders to rmdir after
|
|
||||||
|
|
||||||
self.loud_reply("k")
|
|
||||||
|
|
||||||
def handle_mv(self):
|
def handle_mv(self):
|
||||||
if not self.can_move:
|
if not self.can_move:
|
||||||
|
@ -1586,6 +1567,9 @@ class HttpCli(object):
|
||||||
src = svn.canonical(srem)
|
src = svn.canonical(srem)
|
||||||
dst = dvn.canonical(drem)
|
dst = dvn.canonical(drem)
|
||||||
|
|
||||||
|
if not srem:
|
||||||
|
raise Pebkac(400, "cannot move a mountpoint")
|
||||||
|
|
||||||
self.loud_reply("mv [{}] to [{}]".format(src, dst))
|
self.loud_reply("mv [{}] to [{}]".format(src, dst))
|
||||||
|
|
||||||
def tx_browser(self):
|
def tx_browser(self):
|
||||||
|
|
|
@ -32,6 +32,7 @@ from .util import (
|
||||||
s2hms,
|
s2hms,
|
||||||
min_ex,
|
min_ex,
|
||||||
)
|
)
|
||||||
|
from .authsrv import AuthSrv
|
||||||
from .mtag import MTag, MParser
|
from .mtag import MTag, MParser
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -44,16 +45,9 @@ DB_VER = 4
|
||||||
|
|
||||||
|
|
||||||
class Up2k(object):
|
class Up2k(object):
|
||||||
"""
|
|
||||||
TODO:
|
|
||||||
* documentation
|
|
||||||
* registry persistence
|
|
||||||
* ~/.config flatfiles for active jobs
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, hub):
|
def __init__(self, hub):
|
||||||
self.hub = hub
|
self.hub = hub
|
||||||
self.asrv = hub.asrv
|
self.asrv = hub.asrv # type: AuthSrv
|
||||||
self.args = hub.args
|
self.args = hub.args
|
||||||
self.log_func = hub.log
|
self.log_func = hub.log
|
||||||
|
|
||||||
|
@ -1279,6 +1273,64 @@ class Up2k(object):
|
||||||
v = (wark, int(ts), sz, rd, fn)
|
v = (wark, int(ts), sz, rd, fn)
|
||||||
db.execute(sql, v)
|
db.execute(sql, v)
|
||||||
|
|
||||||
|
def handle_rm(self, uname, vpath):
|
||||||
|
dirs = {}
|
||||||
|
permsets = [[True, False, False, True]]
|
||||||
|
vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0])
|
||||||
|
atop = vn.canonical(rem)
|
||||||
|
adir, fn = os.path.split(atop)
|
||||||
|
|
||||||
|
fun = os.lstat if os.supports_follow_symlinks else os.stat
|
||||||
|
st = fun(fsenc(atop))
|
||||||
|
if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode):
|
||||||
|
g = [[os.path.dirname(vpath), adir, [[fn, 0]], [], []]]
|
||||||
|
else:
|
||||||
|
scandir = not self.args.no_scandir
|
||||||
|
g = vn.walk("", rem, [], uname, permsets, True, scandir, True)
|
||||||
|
|
||||||
|
n_files = 0
|
||||||
|
for dbv, vrem, _, atop, files, rd, vd in g:
|
||||||
|
dirs[atop] = 1
|
||||||
|
for fn in [x[0] for x in files]:
|
||||||
|
n_files += 1
|
||||||
|
abspath = os.path.join(atop, fn)
|
||||||
|
vpath = "{}/{}".format(vrem, fn).strip("/")
|
||||||
|
self.log("rm file {}\n vpath: {}".format(abspath, vpath))
|
||||||
|
# dbv, vrem = self.asrv.vfs.get(vpath, uname, *permsets[0])
|
||||||
|
# dbv, vrem = dbv.get_dbv(vrem)
|
||||||
|
_ = dbv.get(vrem, uname, *permsets[0])
|
||||||
|
with self.mutex:
|
||||||
|
self._drop_file(dbv.realpath, vpath)
|
||||||
|
|
||||||
|
n_dirs = 0
|
||||||
|
for d in dirs.keys():
|
||||||
|
try:
|
||||||
|
os.rmdir(d)
|
||||||
|
n_dirs += 1
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return "deleted {} files (and {}/{} folders)".format(n_files, n_dirs, len(dirs))
|
||||||
|
|
||||||
|
def _drop_file(self, ptop, vrem):
|
||||||
|
cur = self.cur.get(ptop)
|
||||||
|
if cur:
|
||||||
|
q = "delete from up where rd=? and fn=?"
|
||||||
|
rd, fn = os.path.split(vrem)
|
||||||
|
self.log("{}, [{}], [{}]".format(q, rd, fn))
|
||||||
|
# self.db_rm(cur, rd, fn)
|
||||||
|
|
||||||
|
reg = self.registry.get(ptop)
|
||||||
|
if reg:
|
||||||
|
wark = [
|
||||||
|
x
|
||||||
|
for x, y in reg.items()
|
||||||
|
if fn in [y["name"], y.get("tnam")] and y["prel"] == vrem
|
||||||
|
]
|
||||||
|
if wark:
|
||||||
|
self.log("forgetting wark {}".format(wark[0]))
|
||||||
|
del reg[wark[0]]
|
||||||
|
|
||||||
def _get_wark(self, cj):
|
def _get_wark(self, cj):
|
||||||
if len(cj["name"]) > 1024 or len(cj["hash"]) > 512 * 1024: # 16TiB
|
if len(cj["name"]) > 1024 or len(cj["hash"]) > 512 * 1024: # 16TiB
|
||||||
raise Pebkac(400, "name or numchunks not according to spec")
|
raise Pebkac(400, "name or numchunks not according to spec")
|
||||||
|
|
|
@ -383,7 +383,6 @@ html.light #ggrid a.sel {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
top: -1.2em;
|
top: -1.2em;
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 2.5em;
|
|
||||||
height: 1em;
|
height: 1em;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
@ -392,7 +391,7 @@ html.light #ggrid a.sel {
|
||||||
background: #3c3c3c;
|
background: #3c3c3c;
|
||||||
box-shadow: 0 0 .5em #222;
|
box-shadow: 0 0 .5em #222;
|
||||||
border-radius: .3em 0 0 0;
|
border-radius: .3em 0 0 0;
|
||||||
padding: .2em 0 0 .07em;
|
padding: .2em .2em;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
#wzip, #wnp {
|
#wzip, #wnp {
|
||||||
|
@ -414,12 +413,6 @@ html.light #ggrid a.sel {
|
||||||
#wtoggle * {
|
#wtoggle * {
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
#wtoggle.np {
|
|
||||||
width: 6.63em;
|
|
||||||
}
|
|
||||||
#wtoggle.sel {
|
|
||||||
width: 7.57em;
|
|
||||||
}
|
|
||||||
#wtoggle.sel #wzip,
|
#wtoggle.sel #wzip,
|
||||||
#wtoggle.np #wnp {
|
#wtoggle.np #wnp {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -427,15 +420,21 @@ html.light #ggrid a.sel {
|
||||||
#wtoggle.sel.np #wnp {
|
#wtoggle.sel.np #wnp {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
#wfm a,
|
||||||
#wzip a {
|
#wzip a {
|
||||||
font-size: .4em;
|
font-size: .5em;
|
||||||
padding: 0 .3em;
|
padding: 0 .3em;
|
||||||
margin: -.3em .2em;
|
margin: -.3em .2em;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
#wzip a+a {
|
#wfm span {
|
||||||
margin-left: .8em;
|
font-size: .6em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#wzip a {
|
||||||
|
font-size: .4em;
|
||||||
|
margin: -.3em .3em;
|
||||||
}
|
}
|
||||||
#wtoggle.sel #wzip #selzip {
|
#wtoggle.sel #wzip #selzip {
|
||||||
top: -.6em;
|
top: -.6em;
|
||||||
|
|
|
@ -29,7 +29,13 @@ ebi('ops').innerHTML = (
|
||||||
// media player
|
// media player
|
||||||
ebi('widget').innerHTML = (
|
ebi('widget').innerHTML = (
|
||||||
'<div id="wtoggle">' +
|
'<div id="wtoggle">' +
|
||||||
'<span id="wzip"><a' +
|
'<span id="wfm"><a' +
|
||||||
|
' href="#" id="fren" tt="rename selected item$NHotkey: F2">✎<span>name</span></a><a' +
|
||||||
|
' href="#" id="fdel" tt="delete selected items">⌫<span>delete</span></a><a' +
|
||||||
|
' href="#" id="fcut" tt="cut selected items <small>(then paste somewhere else)</small>$NHotkey: ctrl-shift-X">✂<span>cut</span></a><a' +
|
||||||
|
' href="#" id="fcpy" tt="copy selected items <small>(then paste somewhere else)</small>$NHotkey: ctrl-shift-C">⧉<span>copy</span></a><a' +
|
||||||
|
' href="#" id="fpst" tt="paste a previously cut/copied selection$NHotkey: ctrl-shift-V">📋<span>paste</span></a>' +
|
||||||
|
'</span><span id="wzip"><a' +
|
||||||
' href="#" id="selall" tt="select all files">sel.<br />all</a><a' +
|
' href="#" id="selall" tt="select all files">sel.<br />all</a><a' +
|
||||||
' href="#" id="selinv" tt="invert selection">sel.<br />inv.</a><a' +
|
' href="#" id="selinv" tt="invert selection">sel.<br />inv.</a><a' +
|
||||||
' href="#" id="selzip" tt="download selection as archive">zip</a>' +
|
' href="#" id="selzip" tt="download selection as archive">zip</a>' +
|
||||||
|
@ -37,7 +43,7 @@ ebi('widget').innerHTML = (
|
||||||
' href="#" id="npirc" tt="copy irc-formatted track info">📋irc</a><a' +
|
' href="#" id="npirc" tt="copy irc-formatted track info">📋irc</a><a' +
|
||||||
' href="#" id="nptxt" tt="copy plaintext track info">📋txt</a>' +
|
' href="#" id="nptxt" tt="copy plaintext track info">📋txt</a>' +
|
||||||
'</span><a' +
|
'</span><a' +
|
||||||
' href="#" id="wtgrid">田</a><a' +
|
' href="#" id="wtgrid" tt="toggle grid/list view">田</a><a' +
|
||||||
' href="#" id="wtico">♫</a>' +
|
' href="#" id="wtico">♫</a>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div id="widgeti">' +
|
'<div id="widgeti">' +
|
||||||
|
|
|
@ -90,7 +90,7 @@ class TestHttpCli(unittest.TestCase):
|
||||||
if not vol.startswith(top):
|
if not vol.startswith(top):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mode = vol[-2].replace("a", "rw")
|
mode = vol[-2].replace("a", "rwmd")
|
||||||
usr = vol[-1]
|
usr = vol[-1]
|
||||||
if usr == "a":
|
if usr == "a":
|
||||||
usr = ""
|
usr = ""
|
||||||
|
|
Loading…
Reference in a new issue