Scoop icon indicating copy to clipboard operation
Scoop copied to clipboard

Fix #6515 "Expand-7zipArchive won't remove top folder if $ExtractDir depth exceeds 2" - Idea 1

Open o-l-a-v opened this issue 2 months ago • 2 comments

Description

Expand-7zipArchive have had problems with apps where:

  • A directory inside $ExtractDir is named the same as a dir above it (issue #6011, PR #6092)
  • The workaround for above problem did not handle $ExtractDir that are two levels deep or more (issue #6515).
  • To make expansion with $ExtractDir more robust I previously suggested to extract to TEMP first, then move content from there (feature request #6093).

This PR tries to fix all that.

Motivation and Context

  • Closes #6515 and #6093.
  • Relates to #6011

Merging this might break some manifests that have workarounds to delete leftovers after $ExtractDir. Here are some I know of:

How Has This Been Tested?

Checklist:

  • [x] I have read the Contributing Guide.
  • [x] I have ensured that I am targeting the develop branch.
  • [x] I have updated the documentation accordingly.
  • [ ] I have updated the tests accordingly.
  • [x] I have added an entry in the CHANGELOG.

Summary by CodeRabbit

  • New Features

    • Improved partial-extraction workflow: when extracting a subdirectory, files are unpacked to a temporary location and moved into place to ensure reliable results across archive types.
  • Bug Fixes

    • More reliable handling of destination paths and removal of temporary files to prevent leftovers and placement errors.
    • Clearer errors and more consistent external tool invocation for decompression.
  • Documentation

    • Updated changelog documenting decompression and extraction improvements.

o-l-a-v avatar Oct 13 '25 16:10 o-l-a-v

Walkthrough

Updated changelog and refactored decompression handlers in lib/decompress.ps1: archive type detection, consistent external-command invocation, trimmed/normalized destinations, extract-to-temp when ExtractDir is set, then move/cleanup; uniform Remove-Item -Path usage and log cleanup adjustments.

Changes

Cohort / File(s) Summary
Changelog entry
CHANGELOG.md
Adds entry noting that Expand-7zipArchive and Expand-ZipArchive expand into a temp directory when ExtractDir is provided.
Core decompression refactor
lib/decompress.ps1
- Centralized changes across archive handlers: Expand-7zipArchive, Expand-ZipArchive, Expand-MsiArchive, Expand-InnoArchive, Expand-DarkArchive, Expand-ZstdArchive.
- Detects tar archives (IsTar) and adjusts listing/extraction flows.
- Trim/normalize DestinationPath; when ExtractDir provided, extract to a temp path under $env:TEMP then move ExtractDir contents to original destination and remove temp.
- Use Get-Command -Name '7z' for 7z lookup; construct log paths with Split-Path -Path / friendly_path messages.
- Standardize external calls to Invoke-ExternalCommand -FilePath -ArgumentList and status checks (-not $Status).
- Refine post-extract cleanup: remove temp dirs, remove log only if it is a leaf, and consistently use Remove-Item -Path; adjust archive-part removal via Get-ChildItem -Path.
- Minor comment/casing/formatting tweaks for consistency.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant Decompress as lib/decompress.ps1
  participant External as 7z/tar/unzip/msiexec
  participant FS as FileSystem

  Caller->>Decompress: Expand-*(archive, DestinationPath, ExtractDir?)
  Decompress->>Decompress: Trim/normalize DestinationPath\nDetect archive type (IsTar?)
  alt ExtractDir provided
    Decompress->>FS: Create tempDestination under $env:TEMP
    alt Non-tar
      Decompress->>External: Invoke extraction (FilePath + ArgumentList, include -ir!ExtractDir\*)
      External-->>Decompress: Exit status
      Decompress->>FS: Move tempDestination\ExtractDir -> Original DestinationPath
    else Tar
      Decompress->>External: List/extract tar (FilePath + ArgumentList)
      External-->>Decompress: Exit status
      Decompress->>FS: Arrange/move tar contents -> DestinationPath
    end
    Decompress->>FS: Remove tempDestination and cleanup logs (only if leaf)
  else No ExtractDir
    Decompress->>External: Invoke extraction -> DestinationPath
    External-->>Decompress: Exit status
  end
  Decompress->>FS: Optional remove original archive parts (Get-ChildItem -Path / Remove-Item -Path)
  Decompress-->>Caller: Return status/result

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A hop, a zip, a tarball trip—
I nibble paths where temp nests slip.
I tuck ExtractDir in a cozy place,
then hop it home with gentle grace.
Logs and crumbs? I sweep the space. 🐰📦

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning In addition to fixing Expand-7zipArchive, the changes also apply the temporary extraction pattern to Expand-ZipArchive, Expand-MsiArchive, Expand-InnoArchive, Expand-DarkArchive, and Expand-ZstdArchive, which are not covered by the linked issue #6515 focused solely on 7z extraction behavior. Limit the scope of this pull request to only the Expand-7zipArchive changes required by issue #6515 or include additional linked issues that authorize similar modifications for the other archive functions.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues Check ✅ Passed The pull request implements extracting 7z archives to a temporary directory and then moving the specified ExtractDir contents back to the target path, directly addressing the nested‐folder removal issue described in issue #6515. This approach ensures that the top‐level folder is correctly removed regardless of ExtractDir depth, satisfying the linked issue’s requirements.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title clearly references the issue number and the specific Expand-7zipArchive bug it fixes, directly tying to the main change in this pull request. It identifies the problem scope and developer intent in a single sentence. Although it includes some extra wording like “Idea 1” and nested quotes, it still summarizes the central fix for deeper $ExtractDir depths.
✨ Finishing touches
  • [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Oct 13 '25 16:10 coderabbitai[bot]

Merging this might break some manifests that have workarounds to delete leftovers after $ExtractDir. Here are some I know of:

  • https://github.com/ScoopInstaller/Extras/blob/master/bucket/foxit-reader.json
  • https://github.com/ScoopInstaller/Extras/blob/master/bucket/foxit-pdf-reader.json

This isn't specifically meant to remove leftovers ($dir\msi\.rsrc) -- deleting $DestinationPath ($dir\msi) is a common operation.

"Expand-7zipArchive \"$dir\\$fname\" \"$dir\\msi\" -ExtractDir '.rsrc\\1033\\PAYLOAD' -Removal",
"Remove-Item \"$dir\\msi\", \"$dir\\extracted\", \"$dir\\install.log\" -Force -Recurse"

As far as I'm aware, there aren't any related workarounds to delete leftovers after $ExtractDir.

z-Fng avatar Oct 13 '25 20:10 z-Fng