mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -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)
|
||||
dbv, vrem = self.get_dbv(rem)
|
||||
|
||||
if (
|
||||
seen
|
||||
|
@ -259,7 +260,7 @@ class VFS(object):
|
|||
rfiles.sort()
|
||||
rdirs.sort()
|
||||
|
||||
yield rel, fsroot, rfiles, rdirs, vfs_virt
|
||||
yield dbv, vrem, rel, fsroot, rfiles, rdirs, vfs_virt
|
||||
|
||||
for rdir, _ in rdirs:
|
||||
if not dots and rdir.startswith("."):
|
||||
|
@ -287,7 +288,7 @@ class VFS(object):
|
|||
f2b = "{0}.hist{0}".format(os.sep)
|
||||
|
||||
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:
|
||||
files = [x for x in files if x[0] in flt]
|
||||
|
||||
|
@ -795,7 +796,7 @@ class AuthSrv(object):
|
|||
g = vn.walk(
|
||||
"", "", [], 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]
|
||||
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
||||
vpaths = [vtop + x for x in vpaths]
|
||||
|
|
|
@ -1548,27 +1548,8 @@ class HttpCli(object):
|
|||
if self.args.no_del:
|
||||
raise Pebkac(403, "disabled by argv")
|
||||
|
||||
permsets = [[True, False, False, True]]
|
||||
vn, rem = self.asrv.vfs.get(self.vpath, self.uname, *permsets[0])
|
||||
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")
|
||||
x = self.conn.hsrv.broker.put(True, "up2k.handle_rm", self.uname, self.vpath)
|
||||
self.loud_reply(x.get())
|
||||
|
||||
def handle_mv(self):
|
||||
if not self.can_move:
|
||||
|
@ -1586,6 +1567,9 @@ class HttpCli(object):
|
|||
src = svn.canonical(srem)
|
||||
dst = dvn.canonical(drem)
|
||||
|
||||
if not srem:
|
||||
raise Pebkac(400, "cannot move a mountpoint")
|
||||
|
||||
self.loud_reply("mv [{}] to [{}]".format(src, dst))
|
||||
|
||||
def tx_browser(self):
|
||||
|
|
|
@ -32,6 +32,7 @@ from .util import (
|
|||
s2hms,
|
||||
min_ex,
|
||||
)
|
||||
from .authsrv import AuthSrv
|
||||
from .mtag import MTag, MParser
|
||||
|
||||
try:
|
||||
|
@ -44,16 +45,9 @@ DB_VER = 4
|
|||
|
||||
|
||||
class Up2k(object):
|
||||
"""
|
||||
TODO:
|
||||
* documentation
|
||||
* registry persistence
|
||||
* ~/.config flatfiles for active jobs
|
||||
"""
|
||||
|
||||
def __init__(self, hub):
|
||||
self.hub = hub
|
||||
self.asrv = hub.asrv
|
||||
self.asrv = hub.asrv # type: AuthSrv
|
||||
self.args = hub.args
|
||||
self.log_func = hub.log
|
||||
|
||||
|
@ -1279,6 +1273,64 @@ class Up2k(object):
|
|||
v = (wark, int(ts), sz, rd, fn)
|
||||
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):
|
||||
if len(cj["name"]) > 1024 or len(cj["hash"]) > 512 * 1024: # 16TiB
|
||||
raise Pebkac(400, "name or numchunks not according to spec")
|
||||
|
|
|
@ -383,7 +383,6 @@ html.light #ggrid a.sel {
|
|||
white-space: nowrap;
|
||||
top: -1.2em;
|
||||
right: 0;
|
||||
width: 2.5em;
|
||||
height: 1em;
|
||||
font-size: 2em;
|
||||
line-height: 1em;
|
||||
|
@ -392,7 +391,7 @@ html.light #ggrid a.sel {
|
|||
background: #3c3c3c;
|
||||
box-shadow: 0 0 .5em #222;
|
||||
border-radius: .3em 0 0 0;
|
||||
padding: .2em 0 0 .07em;
|
||||
padding: .2em .2em;
|
||||
color: #fff;
|
||||
}
|
||||
#wzip, #wnp {
|
||||
|
@ -414,12 +413,6 @@ html.light #ggrid a.sel {
|
|||
#wtoggle * {
|
||||
line-height: 1em;
|
||||
}
|
||||
#wtoggle.np {
|
||||
width: 6.63em;
|
||||
}
|
||||
#wtoggle.sel {
|
||||
width: 7.57em;
|
||||
}
|
||||
#wtoggle.sel #wzip,
|
||||
#wtoggle.np #wnp {
|
||||
display: inline-block;
|
||||
|
@ -427,15 +420,21 @@ html.light #ggrid a.sel {
|
|||
#wtoggle.sel.np #wnp {
|
||||
display: none;
|
||||
}
|
||||
#wfm a,
|
||||
#wzip a {
|
||||
font-size: .4em;
|
||||
font-size: .5em;
|
||||
padding: 0 .3em;
|
||||
margin: -.3em .2em;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
#wzip a+a {
|
||||
margin-left: .8em;
|
||||
#wfm span {
|
||||
font-size: .6em;
|
||||
display: block;
|
||||
}
|
||||
#wzip a {
|
||||
font-size: .4em;
|
||||
margin: -.3em .3em;
|
||||
}
|
||||
#wtoggle.sel #wzip #selzip {
|
||||
top: -.6em;
|
||||
|
|
|
@ -29,7 +29,13 @@ ebi('ops').innerHTML = (
|
|||
// media player
|
||||
ebi('widget').innerHTML = (
|
||||
'<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="selinv" tt="invert selection">sel.<br />inv.</a><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="nptxt" tt="copy plaintext track info">📋txt</a>' +
|
||||
'</span><a' +
|
||||
' href="#" id="wtgrid">田</a><a' +
|
||||
' href="#" id="wtgrid" tt="toggle grid/list view">田</a><a' +
|
||||
' href="#" id="wtico">♫</a>' +
|
||||
'</div>' +
|
||||
'<div id="widgeti">' +
|
||||
|
|
|
@ -90,7 +90,7 @@ class TestHttpCli(unittest.TestCase):
|
|||
if not vol.startswith(top):
|
||||
continue
|
||||
|
||||
mode = vol[-2].replace("a", "rw")
|
||||
mode = vol[-2].replace("a", "rwmd")
|
||||
usr = vol[-1]
|
||||
if usr == "a":
|
||||
usr = ""
|
||||
|
|
Loading…
Reference in a new issue