Skip to content

fix(files): preserve nested folder structure when archiving workspace files - #5985

Merged
waleedlatif1 merged 1 commit into
stagingfrom
fix/files-export-nested-folders
Jul 27, 2026
Merged

fix(files): preserve nested folder structure when archiving workspace files#5985
waleedlatif1 merged 1 commit into
stagingfrom
fix/files-export-nested-folders

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • file_compress flattened every zip entry to its leaf name, so asking Sim to package a folder produced an archive with all files at the root and (1)/(2) collision suffixes instead of the folder layout
  • Archive entry paths now mirror the workspace folder structure, dropping the ancestor chain the whole selection shares so a single folder is not buried under its parents
  • Added lib/uploads/zip-entry-path.ts as the one place that builds unique, traversal-safe entry paths; the bulk download route reuses it instead of its own copy of the sanitizing and dedup logic
  • Zip-slip protection is unchanged: file names are still reduced to a single segment, and every path segment is sanitized for platform-illegal characters and ./..

Type of Change

  • Bug fix

Testing

Unit tests cover folder mirroring, same-name files across sibling folders, collision suffixing, common-ancestor rebasing (including segment-wise comparison so Reports and Reports-2026 are not treated as nested), and traversal/illegal-character stripping. bun run check:api-validation, typecheck, and the lib/uploads + tools/file suites pass.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

… files

The file_compress tool flattened every entry to its leaf name, so asking Sim
to package a folder produced a zip with all files at the root and collision
suffixes instead of the folder layout.

Archive entry paths now mirror the workspace folder structure, with the
ancestor chain the whole selection shares dropped so a single folder is not
nested under its parents. The bulk download route reuses the same builder
instead of its own copy of the path sanitizing and dedup logic.
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 27, 2026 9:37pm

Request Review

@cursor

cursor Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Behavior change is limited to zip entry naming in download/compress flows; path sanitization is consolidated with tests and does not alter auth or storage.

Overview
Workspace zip archives now keep folder layout instead of flattening every entry to a leaf filename with root-level (1)/(2) collisions.

A shared buildZipEntryPaths helper in lib/uploads/zip-entry-path.ts builds traversal-safe, unique entry paths from each file’s name and workspace folder path. file_compress uses it with rebaseOnCommonFolder so a selection from one folder isn’t wrapped in redundant parent paths; picker/upload inputs still land at the archive root. Bulk workspace download drops its local safeZipPath / dedup logic and calls the same helper for workspace-root-relative paths.

Unit tests cover layout mirroring, cross-folder same names, collision suffixing, rebasing (including segment-wise common ancestors), and sanitization. The file compress tool description notes that folder structure is preserved.

Reviewed by Cursor Bugbot for commit a4de062. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR centralizes safe ZIP-entry path construction and preserves workspace folder structure in generated archives.

  • Adds a shared helper for sanitization, common-folder rebasing, and deterministic collision suffixing.
  • Updates file compression to retain nested workspace paths while removing shared ancestors.
  • Reuses the helper in bulk workspace downloads and adds focused unit coverage.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code defects identified.

The shared helper preserves source ordering, sanitizes every generated path segment, prevents duplicate ZIP entries, and applies common-folder rebasing only on the compression path where it is intended.

Important Files Changed

Filename Overview
apps/sim/lib/uploads/zip-entry-path.ts Introduces ordered, traversal-safe ZIP path construction with optional common-folder rebasing and collision handling.
apps/sim/app/api/tools/file/manage/route.ts Associates resolved workspace files with their folder paths and uses rebased paths when constructing compression archives.
apps/sim/app/api/workspaces/[id]/files/download/route.ts Replaces duplicated ZIP sanitization and deduplication logic with the shared path builder.
apps/sim/lib/uploads/zip-entry-path.test.ts Covers hierarchy preservation, rebasing, collisions, traversal sanitization, and fallback behavior.
apps/sim/tools/file/compress.ts Updates the tool description to document preservation of workspace folder structure.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  S[Selected workspace files] --> M[Associate names with folder paths]
  M --> R{Compress tool?}
  R -->|Yes| C[Remove shared folder prefix]
  R -->|No| K[Keep workspace-root-relative paths]
  C --> Z[Sanitize path segments]
  K --> Z
  Z --> D[Suffix duplicate entry paths]
  D --> A[Generate ZIP archive]
Loading

Reviews (1): Last reviewed commit: "fix(files): preserve nested folder struc..." | Re-trigger Greptile

@waleedlatif1
waleedlatif1 merged commit 4edc169 into staging Jul 27, 2026
20 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/files-export-nested-folders branch July 27, 2026 22:04
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.

1 participant