mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
preserve empty folders (closes #23):
* when deleting files, do not cascade upwards through empty folders * when moving folders, also move any empty folders inside the only remaining action which autoremoves empty folders is files getting deleted as they expire volume lifetimes also prevents accidentally moving parent folders into subfolders (even though that actually worked surprisingly well)
This commit is contained in:
parent
c44f5f5701
commit
83178d0836
|
@ -271,7 +271,7 @@ class FtpFs(AbstractedFS):
|
|||
|
||||
vp = join(self.cwd, path).lstrip("/")
|
||||
try:
|
||||
self.hub.up2k.handle_rm(self.uname, self.h.cli_ip, [vp], [])
|
||||
self.hub.up2k.handle_rm(self.uname, self.h.cli_ip, [vp], [], False)
|
||||
except Exception as ex:
|
||||
raise FSE(str(ex))
|
||||
|
||||
|
|
|
@ -1152,18 +1152,9 @@ class HttpCli(object):
|
|||
dst = self.headers["destination"]
|
||||
dst = re.sub("^https?://[^/]+", "", dst).lstrip()
|
||||
dst = unquotep(dst)
|
||||
if not self._mv(self.vpath, dst):
|
||||
if not self._mv(self.vpath, dst.lstrip("/")):
|
||||
return False
|
||||
|
||||
# up2k only cares about files and removes all empty folders;
|
||||
# clients naturally expect empty folders to survive a rename
|
||||
vn, rem = self.asrv.vfs.get(dst, self.uname, False, False)
|
||||
dabs = vn.canonical(rem)
|
||||
try:
|
||||
bos.makedirs(dabs)
|
||||
except:
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
def _applesan(self) -> bool:
|
||||
|
@ -3054,7 +3045,7 @@ class HttpCli(object):
|
|||
ret = self.gen_tree(top, dst)
|
||||
if self.is_vproxied:
|
||||
parents = self.args.R.split("/")
|
||||
for parent in parents[::-1]:
|
||||
for parent in reversed(parents):
|
||||
ret = {"k%s" % (parent,): ret, "a": []}
|
||||
|
||||
zs = json.dumps(ret)
|
||||
|
@ -3193,7 +3184,9 @@ class HttpCli(object):
|
|||
nlim = int(self.uparam.get("lim") or 0)
|
||||
lim = [nlim, nlim] if nlim else []
|
||||
|
||||
x = self.conn.hsrv.broker.ask("up2k.handle_rm", self.uname, self.ip, req, lim)
|
||||
x = self.conn.hsrv.broker.ask(
|
||||
"up2k.handle_rm", self.uname, self.ip, req, lim, False
|
||||
)
|
||||
self.loud_reply(x.get())
|
||||
return True
|
||||
|
||||
|
@ -3210,7 +3203,7 @@ class HttpCli(object):
|
|||
# x-www-form-urlencoded (url query part) uses
|
||||
# either + or %20 for 0x20 so handle both
|
||||
dst = unquotep(dst.replace("+", " "))
|
||||
return self._mv(self.vpath, dst)
|
||||
return self._mv(self.vpath, dst.lstrip("/"))
|
||||
|
||||
def _mv(self, vsrc: str, vdst: str) -> bool:
|
||||
if not self.can_move:
|
||||
|
|
|
@ -261,7 +261,7 @@ class SMB(object):
|
|||
yeet("blocked delete (no-del-acc): " + vpath)
|
||||
|
||||
vpath = vpath.replace("\\", "/").lstrip("/")
|
||||
self.hub.up2k.handle_rm(LEELOO_DALLAS, "1.7.6.2", [vpath], [])
|
||||
self.hub.up2k.handle_rm(LEELOO_DALLAS, "1.7.6.2", [vpath], [], False)
|
||||
|
||||
def _utime(self, vpath: str, times: tuple[float, float]) -> None:
|
||||
if not self.args.smbw:
|
||||
|
|
|
@ -384,7 +384,7 @@ class Up2k(object):
|
|||
if vp:
|
||||
fvp = "%s/%s" % (vp, fvp)
|
||||
|
||||
self._handle_rm(LEELOO_DALLAS, "", fvp, [])
|
||||
self._handle_rm(LEELOO_DALLAS, "", fvp, [], True)
|
||||
nrm += 1
|
||||
|
||||
if nrm:
|
||||
|
@ -2897,7 +2897,9 @@ class Up2k(object):
|
|||
except:
|
||||
pass
|
||||
|
||||
def handle_rm(self, uname: str, ip: str, vpaths: list[str], lim: list[int]) -> str:
|
||||
def handle_rm(
|
||||
self, uname: str, ip: str, vpaths: list[str], lim: list[int], rm_up: bool
|
||||
) -> str:
|
||||
n_files = 0
|
||||
ok = {}
|
||||
ng = {}
|
||||
|
@ -2906,7 +2908,7 @@ class Up2k(object):
|
|||
self.log("hit delete limit of {} files".format(lim[1]), 3)
|
||||
break
|
||||
|
||||
a, b, c = self._handle_rm(uname, ip, vp, lim)
|
||||
a, b, c = self._handle_rm(uname, ip, vp, lim, rm_up)
|
||||
n_files += a
|
||||
for k in b:
|
||||
ok[k] = 1
|
||||
|
@ -2920,7 +2922,7 @@ class Up2k(object):
|
|||
return "deleted {} files (and {}/{} folders)".format(n_files, iok, iok + ing)
|
||||
|
||||
def _handle_rm(
|
||||
self, uname: str, ip: str, vpath: str, lim: list[int]
|
||||
self, uname: str, ip: str, vpath: str, lim: list[int], rm_up: bool
|
||||
) -> tuple[int, list[str], list[str]]:
|
||||
self.db_act = time.time()
|
||||
try:
|
||||
|
@ -3027,16 +3029,22 @@ class Up2k(object):
|
|||
if xad:
|
||||
runhook(self.log, xad, abspath, vpath, "", uname, 0, 0, ip, 0, "")
|
||||
|
||||
ok: list[str] = []
|
||||
ng: list[str] = []
|
||||
if is_dir:
|
||||
ok, ng = rmdirs(self.log_func, scandir, True, atop, 1)
|
||||
else:
|
||||
ok = ng = []
|
||||
|
||||
if rm_up:
|
||||
ok2, ng2 = rmdirs_up(os.path.dirname(atop), ptop)
|
||||
else:
|
||||
ok2 = ng2 = []
|
||||
|
||||
return n_files, ok + ok2, ng + ng2
|
||||
|
||||
def handle_mv(self, uname: str, svp: str, dvp: str) -> str:
|
||||
if svp == dvp or dvp.startswith(svp + "/"):
|
||||
raise Pebkac(400, "mv: cannot move parent into subfolder")
|
||||
|
||||
svn, srem = self.asrv.vfs.get(svp, uname, True, False, True)
|
||||
svn, srem = svn.get_dbv(srem)
|
||||
sabs = svn.canonical(srem, False)
|
||||
|
@ -3090,8 +3098,21 @@ class Up2k(object):
|
|||
|
||||
curs.clear()
|
||||
|
||||
rmdirs(self.log_func, scandir, True, sabs, 1)
|
||||
rmdirs_up(os.path.dirname(sabs), svn.realpath)
|
||||
rm_ok, rm_ng = rmdirs(self.log_func, scandir, True, sabs, 1)
|
||||
|
||||
for zsl in (rm_ok, rm_ng):
|
||||
for ap in reversed(zsl):
|
||||
if not ap.startswith(sabs):
|
||||
raise Pebkac(500, "mv_d: bug at {}, top {}".format(ap, sabs))
|
||||
|
||||
rem = ap[len(sabs) :].replace(os.sep, "/").lstrip("/")
|
||||
vp = vjoin(dvp, rem)
|
||||
try:
|
||||
dvn, drem = self.asrv.vfs.get(vp, uname, False, True)
|
||||
bos.mkdir(dvn.canonical(drem))
|
||||
except:
|
||||
pass
|
||||
|
||||
return "k"
|
||||
|
||||
def _mv_file(
|
||||
|
|
|
@ -2270,7 +2270,7 @@ def rmdirs(
|
|||
dirs = [os.path.join(top, x) for x in dirs]
|
||||
ok = []
|
||||
ng = []
|
||||
for d in dirs[::-1]:
|
||||
for d in reversed(dirs):
|
||||
a, b = rmdirs(logger, scandir, lstat, d, depth + 1)
|
||||
ok += a
|
||||
ng += b
|
||||
|
|
Loading…
Reference in a new issue