util.copy(): Add recursive directory copy
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m51s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m42s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m53s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m46s
CI / Packaging test (push) Successful in 0s
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m51s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m42s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m53s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m46s
CI / Packaging test (push) Successful in 0s
copy() copies a single file: it fetches the source root as one content and puts it at the destination, so addressing a directory source fails, and there is no way to mirror a tree between file contexts. Add a recursive mode: - a directory source is mirrored below the destination root, into it if the root is an existing directory, as it if it does not exist yet - entries are enumerated with readdir(), destination directories are created level by level, and every leaf is put with the requested owner, group, and mode - a file source is unaffected, and the destination parent must exist, as before posix copy exposes the mode as -r/--recursive; the help test reference picks up the new option. Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.87.1 Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
0c732672ed
commit
b697b7b754
2 changed files with 177 additions and 2 deletions
|
|
@ -27,6 +27,12 @@ class CmdCopy(Cmd): # export
|
|||
parser.add_argument(
|
||||
'-m', '--mode', default = None, help = 'Destination file mode'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--recursive',
|
||||
action = 'store_true',
|
||||
help = 'Copy directories recursively',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-F',
|
||||
'--fixed-strings',
|
||||
|
|
@ -53,4 +59,5 @@ class CmdCopy(Cmd): # export
|
|||
owner = args.owner,
|
||||
group = args.group,
|
||||
mode = int(args.mode, 0),
|
||||
recursive = args.recursive,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -174,11 +174,12 @@ async def copy(
|
|||
group: str | None = None,
|
||||
mode: int | None = None,
|
||||
throw: bool = True,
|
||||
recursive: bool = False,
|
||||
) -> Exception | str | list[str]:
|
||||
if not isinstance(src_uri, str):
|
||||
ret: list[str] = []
|
||||
for uri in src_uri: # TODO: Group identical netlocs into one CopyContext
|
||||
rr = await copy(uri, dst, owner, group, mode, throw)
|
||||
rr = await copy(uri, dst, owner, group, mode, throw, recursive)
|
||||
if isinstance(rr, Exception):
|
||||
return rr
|
||||
if isinstance(rr, list):
|
||||
|
|
@ -191,7 +192,50 @@ async def copy(
|
|||
from .CopyContext import CopyContext
|
||||
|
||||
async with CopyContext(src_uri, dst) as ctx:
|
||||
|
||||
async def __mkdir_p(path: str) -> None:
|
||||
# -- Create each level of the destination path that does not
|
||||
# exist yet; put() does not create parent directories
|
||||
cur = ''
|
||||
for part in path.strip('/').split('/'):
|
||||
cur = f'{cur}/{part}'
|
||||
if not await ctx.dst.is_dir(cur):
|
||||
await ctx.dst.mkdir(cur)
|
||||
|
||||
async def __copy_tree(src_path: str, dst_path: str) -> list[str]:
|
||||
ret: list[str] = []
|
||||
for entry in await ctx.src.readdir(src_path):
|
||||
s_path = f'{src_path}/{entry}'
|
||||
d_path = f'{dst_path}/{entry}'
|
||||
if await ctx.src.is_dir(s_path):
|
||||
await __mkdir_p(d_path)
|
||||
ret.extend(await __copy_tree(s_path, d_path))
|
||||
else:
|
||||
result = await ctx.src.get(s_path, throw = True)
|
||||
parent = d_path.rpartition('/')[0]
|
||||
if parent:
|
||||
await __mkdir_p(parent)
|
||||
await ctx.dst.put(
|
||||
path = d_path,
|
||||
content = result.stdout,
|
||||
owner = owner,
|
||||
group = group,
|
||||
mode = mode,
|
||||
throw = True,
|
||||
)
|
||||
ret.append(d_path)
|
||||
return ret
|
||||
|
||||
try:
|
||||
if recursive and await ctx.src.is_dir(ctx.src.root):
|
||||
# -- A directory source is mirrored below the destination
|
||||
# root: into it, if the root is an existing directory,
|
||||
# as it, if it does not exist yet
|
||||
dst_root = ctx.dst.root
|
||||
if await ctx.dst.is_dir(dst_root):
|
||||
dst_root += '/' + os.path.basename(src_uri)
|
||||
await __mkdir_p(dst_root)
|
||||
return await __copy_tree(ctx.src.root, dst_root)
|
||||
result = await ctx.src.get(ctx.src.root, throw = True)
|
||||
dst_path = ctx.dst.root
|
||||
if await ctx.dst.is_dir(ctx.dst.root):
|
||||
|
|
|
|||
Loading…
Reference in a new issue