Skip to content

fix: disambiguate archive entries when multiple inputs share the same basename#999

Open
toller892 wants to merge 1 commit into
ouch-org:mainfrom
toller892:fix/duplicate-basename-collision
Open

fix: disambiguate archive entries when multiple inputs share the same basename#999
toller892 wants to merge 1 commit into
ouch-org:mainfrom
toller892:fix/duplicate-basename-collision

Conversation

@toller892
Copy link
Copy Markdown

Problem

When compressing multiple directories with the same basename (e.g., /mnt/d/Temp/GOG/Scripts and /mnt/d/Temp/kodi/Scripts), ouch strips paths to just the basename using file_name(). This causes:

  • Zip: "Invalid zip archive - Duplicate filename: Scripts/"
  • Tar: both directories merge into one, causing data loss on decompress

Fixes #978

Root Cause

In all three archive builders (tar, zip, 7z), the build_archive function:

  1. Calls cd_into_same_dir_as(explicit_path) to change cwd to the parent directory
  2. Uses explicit_path.file_name().unwrap() to get just the basename
  3. The walker walks from the basename, so archive entries are just Scripts/...

When two inputs share the same basename, they collide.

Fix

When input paths have duplicate basenames, compute the common ancestor directory of all inputs and store archive entries relative to it, including enough parent path components to disambiguate (e.g., parent1/Scripts vs parent2/Scripts).

When basenames don't collide, behavior is unchanged (backward compatible).

Example

# Before (broken):
ouch compress /a/parent1/Scripts /a/parent2/Scripts archive.tar
# Archive contains: Scripts/a.txt, Scripts/b.txt  <-- COLLISION!

# After (fixed):  
ouch compress /a/parent1/Scripts /a/parent2/Scripts archive.tar
# Archive contains: parent1/Scripts/a.txt, parent2/Scripts/b.txt  <-- no collision

Files Changed

  • src/utils/fs.rs - Added has_duplicate_basenames() and common_ancestor() helper functions
  • src/archive/tar.rs - Use common ancestor approach when basenames collide
  • src/archive/zip.rs - Same fix for zip builder
  • src/archive/sevenz.rs - Same fix for 7z builder
  • tests/integration.rs - Added tests for tar and zip with duplicate basenames

Test Results

All 91 tests pass (34 unit + 39 integration + 3 mime + 13 UI + 2 utils), including the 2 new tests:

  • compress_dirs_with_same_basename_tar
  • compress_dirs_with_same_basename_zip

… basename

When compressing multiple directories that share the same basename
(e.g., /a/parent1/Scripts and /a/parent2/Scripts), ouch previously
stripped paths to just the basename using file_name(). This caused:
- Zip: 'Invalid zip archive - Duplicate filename: Scripts/'
- Tar: both directories merge into one, data loss on decompress

Fix: detect when input paths have duplicate basenames and, in that
case, compute the common ancestor directory of all inputs. Archive
entries are then stored relative to this common ancestor, including
enough parent path components to disambiguate (e.g., parent1/Scripts
vs parent2/Scripts).

When basenames don't collide, behavior is unchanged (backward compatible).

Applied consistently to all three archive builders: tar, zip, and 7z.

Fixes ouch-org#978
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle better multiple paths with the same basename

1 participant