fix: flatten nested single-child directories after extraction
Archives like Debian_13_VMG.7z contain nested single-child dirs: Debian_13_VMG_LinuxVMImages.COM/Debian_13_VMG_LinuxVMImages.COM/ _flatten_nested() collapses these chains until files sit directly in the parent, eliminating the double-nesting issue.
This commit is contained in:
parent
a28e2af674
commit
9dcde5d022
1 changed files with 31 additions and 11 deletions
|
|
@ -110,18 +110,38 @@ def extract_if_needed(filename: str) -> Path:
|
|||
# If the archive had a single top-level directory matching the stem, use it
|
||||
expected_dir = STAGING_IN / stem
|
||||
if expected_dir in new_items and expected_dir.is_dir():
|
||||
return expected_dir
|
||||
result = expected_dir
|
||||
else:
|
||||
# Collect scattered files into a subdirectory
|
||||
out_dir = STAGING_IN / stem
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
for item in new_items:
|
||||
shutil.move(str(item), str(out_dir / item.name))
|
||||
result = out_dir
|
||||
|
||||
# Otherwise, collect scattered files into a subdirectory
|
||||
out_dir = STAGING_IN / stem
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
for item in new_items:
|
||||
dest = out_dir / item.name
|
||||
if item.is_dir():
|
||||
shutil.move(str(item), str(dest))
|
||||
else:
|
||||
shutil.move(str(item), str(dest))
|
||||
return out_dir
|
||||
# Flatten nested single-child directories (archive quirk)
|
||||
result = _flatten_nested(result)
|
||||
return result
|
||||
|
||||
|
||||
def _flatten_nested(base: Path) -> Path:
|
||||
"""If a directory has exactly one child that is also a directory,
|
||||
move the child's contents up and remove the child. Repeat until stable.
|
||||
Returns the (possibly changed) base path."""
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
if not base.is_dir():
|
||||
break
|
||||
entries = [e for e in base.iterdir() if e.name not in ('.', '..')]
|
||||
if len(entries) == 1 and entries[0].is_dir():
|
||||
inner = entries[0]
|
||||
# Move everything from inner into base
|
||||
for item in list(inner.iterdir()):
|
||||
shutil.move(str(item), str(base / item.name))
|
||||
inner.rmdir()
|
||||
changed = True
|
||||
return base
|
||||
|
||||
|
||||
def _detect_archive_ext(name: str) -> Optional[str]:
|
||||
|
|
|
|||
Loading…
Reference in a new issue