GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||
GeezerVison is showing github.com — fix(uploads): restore archive extraction folder parity by waleedlatif1 · Pull Request #6565 · simstudioai/sim Conversation
Collaborator
Stacked on #6560 ( Archive extraction regressed against The three defects
FixAdds Deliberately not a one-line Tests
Known gap (deliberate)The new operation has no type-check · biome · 937 tests (
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Archive extraction into workspace files/ was rewritten onto the authorized application-operation boundary, and three behavioral regressions came with that move. Together they broke every archive containing a subdirectory, and 100% of copilot extract() calls (materialize-file always passes rootFolderSegments: [baseName], and its catch only handles ArchiveError). 1. Non-canonical folder path. The extractor joined the folder segments with "/" and passed the result as `path` to createWorkspaceFileFolderOperation. That path reaches requireNonRootFolderPath -> parseFolderPath, which requires a leading "/" and byte-for-byte canonical per-segment encoding, so "bundle/data" threw FolderPathError before anything was written — and a folder name containing a space or a reserved character would still have thrown after merely prefixing a slash. 2. exactName: true. createWorkspaceFileFromBuffer was told to demand the exact leaf name, which sets maxAttempts = 1 and raises FileConflictError when the name already exists. The extractor's rollback then deleted every file written so far, so one colliding name destroyed the whole extraction. Reachable today for flat archives through the unzip action of POST /api/tools/file/manage. Restored to auto-suffixing via allocateUniqueWorkspaceFileName. 3. Wrong folder primitive. createWorkspaceFileFolderAtPath creates exactly one leaf, conflicts on an existing path, and requires the parent to exist already. The extractor never creates intermediates and caches by full path, so the first nested entry asked for a folder whose parent was never created. The correct semantics are ensureWorkspaceFileFolderPath: walk every segment, reuse what exists, create only what is missing. Rather than bypass the operation boundary by calling the manager primitive directly, this adds ensureWorkspaceFileFolderPathOperation — an authorized application use case under files.folders.create that expresses "ensure this whole chain exists" — and routes the extractor through it with raw decoded segments, so no path string is built and no encoding can be malformed. archive.test.ts previously mocked the folder operation and asserted the broken shape (path: 'bundle'), which is why this shipped. The suite now fakes the workspace-file store in memory while enforcing the real rules: folder paths run through the production parseFolderPath family, the create-one-leaf operation conflicts and requires a parent, and exactName governs conflict vs auto-suffix. Nested, reuse, encoded-name, and collision cases are covered and each fails against the pre-fix code.
|
There was an error while loading. Please reload this page.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
PR SummaryMedium Risk Overview Archive extraction now calls
Reviewed by Cursor Bugbot for commit 427b260. Configure here. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Greptile SummaryThis PR restores archive extraction behavior by materializing complete folder chains, reusing existing folders, auto-suffixing colliding filenames, and cleaning up extraction-created folders after failures.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/uploads/archive.ts | Uses ensure semantics for archive folder chains, enables collision suffixing, and extends failure rollback to folders created during extraction. |
| apps/sim/lib/uploads/contexts/workspace/workspace-file-folder-manager.ts | Extends folder-path ensuring to return the deepest folder ID and the ordered IDs inserted by the call. |
| apps/sim/lib/workspace-files/application/workspace-file-folders.ts | Exposes folder-path ensuring through the existing authorized workspace-file operation boundary. |
| apps/sim/lib/workspace-files/application/write-workspace-file-by-path.ts | Adapts existing path-based file writers to the ensure helper’s new structured result. |
| apps/sim/lib/uploads/archive.test.ts | Adds contract-oriented coverage for nested paths, encoded names, existing folders, filename conflicts, and rollback ordering. |
sequenceDiagram
participant Caller
participant Extractor
participant FolderOp as Ensure Folder Path
participant Upload as File Upload
participant Cleanup as Delete Operations
Caller->>Extractor: Extract archive
loop Each archive entry
Extractor->>FolderOp: Ensure decoded path segments
FolderOp-->>Extractor: folderId, createdFolderIds
Extractor->>Upload: "Create file with exactName=false"
Upload-->>Extractor: Created file
end
alt Extraction succeeds
Extractor-->>Caller: Extracted files
else Any operation fails
Extractor->>Cleanup: Delete created files
Extractor->>Cleanup: Delete created folders deepest-first
Extractor-->>Caller: Original error
end
Reviews (2): Last reviewed commit: "fix(uploads): roll back folders archive ..." | Re-trigger Greptile
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Extraction now materializes folders before uploading files, but the failure path only deleted the extracted files — every folder the call created was left behind. That is not cosmetic: `materialize_file` guards re-extraction by looking up the root folder path and refusing when it has any child, so a half-extracted nested archive turned every retry into "already extracted — delete that folder first" until a human cleaned up the tree by hand. The rollback must delete only folders this call actually inserted, never one it reused: extracting into an existing path is normal (a sibling entry, an earlier successful extraction), and deleting a pre-existing folder would destroy unrelated user data. `ensureWorkspaceFileFolderPath` already distinguishes the two while walking the segment chain, so it (and its application operation) now reports `createdFolderIds` alongside the leaf id. The extractor accumulates those ids in creation order and, on failure, deletes them in reverse — parents are recorded before their children, so reverse order is deepest-first and a parent is never removed out from under a child. Folder cleanup is best-effort like the existing file cleanup, so a cleanup failure never masks the original error.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@cursor review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 427b260. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| } | ||
|
|
||
| return parentId | ||
| return { folderId: parentId, createdFolderIds } |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
High Severity
ensureWorkspaceFileFolderPath only returns createdFolderIds on success. If it throws after inserting some segments, those IDs never reach archive rollback, so the new folder unwind cannot run. Leftover folders under the extract root still trip the materialize_file content guard and block every retry.
Reviewed by Cursor Bugbot for commit 427b260. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
7af315f
into
improvement/v2-route-standardization
There was an error while loading. Please reload this page.
427b2606
Deployed
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.