mv/del: recursive rmdir

This commit is contained in:
ed 2021-07-27 19:15:58 +02:00
parent 1ad7a3f378
commit 129d33f1a0
3 changed files with 35 additions and 25 deletions

View file

@ -30,6 +30,7 @@ from .util import (
vsplit, vsplit,
s3enc, s3enc,
s3dec, s3dec,
rmdirs,
statdir, statdir,
s2hms, s2hms,
min_ex, min_ex,
@ -1305,27 +1306,25 @@ class Up2k(object):
db.execute(sql, v) db.execute(sql, v)
def handle_rm(self, uname, vpath): def handle_rm(self, uname, vpath):
dirs = {}
permsets = [[True, False, False, True]] permsets = [[True, False, False, True]]
vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0]) vn, rem = self.asrv.vfs.get(vpath, uname, *permsets[0])
ptop = vn.realpath ptop = vn.realpath
atop = vn.canonical(rem) atop = vn.canonical(rem)
adir, fn = os.path.split(atop) adir, fn = os.path.split(atop)
st = bos.lstat(atop) st = bos.lstat(atop)
scandir = not self.args.no_scandir
if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode): if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode):
dbv, vrem = self.asrv.vfs.get(vpath, uname, *permsets[0]) dbv, vrem = self.asrv.vfs.get(vpath, uname, *permsets[0])
dbv, vrem = dbv.get_dbv(vrem) dbv, vrem = dbv.get_dbv(vrem)
g = [[dbv, vrem, os.path.dirname(vpath), adir, [[fn, 0]], [], []]] g = [[dbv, vrem, os.path.dirname(vpath), adir, [[fn, 0]], [], []]]
else: else:
scandir = not self.args.no_scandir
g = vn.walk("", rem, [], uname, permsets, True, scandir, True) g = vn.walk("", rem, [], uname, permsets, True, scandir, True)
n_files = 0 n_files = 0
for dbv, vrem, _, atop, files, rd, vd in g: for dbv, vrem, _, adir, files, rd, vd in g:
dirs[atop] = 1
for fn in [x[0] for x in files]: for fn in [x[0] for x in files]:
n_files += 1 n_files += 1
abspath = os.path.join(atop, fn) abspath = os.path.join(adir, fn)
vpath = "{}/{}".format(vrem, fn).strip("/") vpath = "{}/{}".format(vrem, fn).strip("/")
self.log("rm {}\n {}".format(vpath, abspath)) self.log("rm {}\n {}".format(vpath, abspath))
_ = dbv.get(vrem, uname, *permsets[0]) _ = dbv.get(vrem, uname, *permsets[0])
@ -1339,15 +1338,10 @@ class Up2k(object):
bos.unlink(abspath) bos.unlink(abspath)
n_dirs = 0 rm = rmdirs(self.log_func, scandir, True, atop)
for d in dirs.keys(): ok = len(rm[0])
try: ng = len(rm[1])
bos.rmdir(d) return "deleted {} files (and {}/{} folders)".format(n_files, ok, ok + ng)
n_dirs += 1
except:
pass
return "deleted {} files (and {}/{} folders)".format(n_files, n_dirs, len(dirs))
def handle_mv(self, uname, svp, dvp): def handle_mv(self, uname, svp, dvp):
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True) svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
@ -1372,14 +1366,12 @@ class Up2k(object):
# fail early (prevent partial moves) # fail early (prevent partial moves)
raise Pebkac(400, "mv: source folder contains other volumes") raise Pebkac(400, "mv: source folder contains other volumes")
dirs = {}
g = svn.walk("", srem, [], uname, permsets, True, scandir, True) g = svn.walk("", srem, [], uname, permsets, True, scandir, True)
for dbv, vrem, _, atop, files, rd, vd in g: for dbv, vrem, _, atop, files, rd, vd in g:
if dbv != jail: if dbv != jail:
# the actual check (avoid toctou) # the actual check (avoid toctou)
raise Pebkac(400, "mv: source folder contains other volumes") raise Pebkac(400, "mv: source folder contains other volumes")
dirs[atop] = 1
for fn in files: for fn in files:
svpf = "/".join(x for x in [dbv.vpath, vrem, fn[0]] if x) svpf = "/".join(x for x in [dbv.vpath, vrem, fn[0]] if x)
if not svpf.startswith(svp + "/"): # assert if not svpf.startswith(svp + "/"): # assert
@ -1388,12 +1380,7 @@ class Up2k(object):
dvpf = dvp + svpf[len(svp) :] dvpf = dvp + svpf[len(svp) :]
self._mv_file(uname, svpf, dvpf) self._mv_file(uname, svpf, dvpf)
for d in list(dirs.keys()) + [sabs]: rmdirs(self.log_func, scandir, True, sabs)
try:
bos.rmdir(d)
except:
pass
return "k" return "k"
def _mv_file(self, uname, svp, dvp): def _mv_file(self, uname, svp, dvp):

View file

@ -4,6 +4,7 @@ from __future__ import print_function, unicode_literals
import re import re
import os import os
import sys import sys
import stat
import time import time
import base64 import base64
import select import select
@ -1061,6 +1062,26 @@ def statdir(logger, scandir, lstat, top):
logger(src, "{} @ {}".format(repr(ex), top), 1) logger(src, "{} @ {}".format(repr(ex), top), 1)
def rmdirs(logger, scandir, lstat, top):
dirs = statdir(logger, scandir, lstat, top)
dirs = [x[0] for x in dirs if stat.S_ISDIR(x[1].st_mode)]
dirs = [os.path.join(top, x) for x in dirs]
ok = []
ng = []
for d in dirs[::-1]:
a, b = rmdirs(logger, scandir, lstat, d)
ok += a
ng += b
try:
os.rmdir(fsenc(top))
ok.append(top)
except:
ng.append(top)
return ok, ng
def unescape_cookie(orig): def unescape_cookie(orig):
# mw=idk; doot=qwe%2Crty%3Basd+fgh%2Bjkl%25zxc%26vbn # qwe,rty;asd fgh+jkl%zxc&vbn # mw=idk; doot=qwe%2Crty%3Basd+fgh%2Bjkl%25zxc%26vbn # qwe,rty;asd fgh+jkl%zxc&vbn
ret = "" ret = ""

View file

@ -1555,7 +1555,7 @@ var fileman = (function () {
treectl.goto(get_evpath()); treectl.goto(get_evpath());
return; return;
} }
toast.inf(2, 'deleting ' + (vps.length + 1) + ' items\n\n' + vp); toast.inf(0, 'deleting ' + (vps.length + 1) + ' items\n\n' + vp);
xhr.open('GET', vp + '?delete', true); xhr.open('GET', vp + '?delete', true);
xhr.onreadystatechange = delete_cb; xhr.onreadystatechange = delete_cb;
@ -1642,7 +1642,7 @@ var fileman = (function () {
r.tx(srcdir); r.tx(srcdir);
return; return;
} }
toast.inf(2, 'pasting ' + (req.length + 1) + ' items\n\n' + vp); toast.inf(0, 'pasting ' + (req.length + 1) + ' items\n\n' + vp);
var dst = get_evpath() + vp.split('/').slice(-1)[0]; var dst = get_evpath() + vp.split('/').slice(-1)[0];
@ -2034,8 +2034,10 @@ document.onkeydown = function (e) {
if (ctrl(e)) if (ctrl(e))
document.documentElement.scrollTop += (d == 'next' ? 1 : -1) * el.offsetHeight; document.documentElement.scrollTop += (d == 'next' ? 1 : -1) * el.offsetHeight;
if (e.shiftKey) if (e.shiftKey) {
clmod(el, 'sel', 't'); clmod(el, 'sel', 't');
msel.selui();
}
return ev(e); return ev(e);
} }