Skip to content

fix: address 2 bugs from Devin Review on workspaceStore#7

Merged
Huynhthuongg merged 1 commit into
mainfrom
devin/1777470417-fix-devin-review-bugs
Apr 29, 2026
Merged

fix: address 2 bugs from Devin Review on workspaceStore#7
Huynhthuongg merged 1 commit into
mainfrom
devin/1777470417-fix-devin-review-bugs

Conversation

@devin-ai-integration

Copy link
Copy Markdown

Summary

Fixes 2 bugs identified by Devin Review on PR #3:

  1. duplicateFile for folders creates children with duplicate IDs and stale paths — When duplicating a folder, newNode was constructed via ...node spread, which copied the children array by reference. Every child inside a duplicated folder retained its original id and original path (pointing to the old parent). Added deepCloneFileNode() helper that recursively clones a FileNode tree, generating new IDs via genId and updating paths for each child.

  2. updateChildrenPaths uses String.replace which isn't anchored to the path prefixchild.path.replace(oldPath, newPath) treats $&, $`, $', and $$ as special replacement patterns in newPath, which could corrupt paths if a folder is renamed to a name containing those characters. Replaced with startsWith + slice for safe, prefix-anchored path updates.

Review & Testing Checklist for Human

  • Duplicate a folder (e.g. right-click /src/styles → Duplicate) and verify the copy's children have unique IDs and paths pointing to the new parent folder (e.g. /src/styles (copy)/global.css)
  • Rename a folder to a name containing $& or $$ and verify children's paths are updated correctly without corruption
  • Duplicate a root-level file and verify it still works correctly

Notes

  • TypeScript and ESLint checks pass cleanly
  • No changes to component files; only src/stores/workspaceStore.ts was modified

Link to Devin session: https://app.devin.ai/sessions/18093fc66df54f558a2031925bd13886
Requested by: @Huynhthuongg

1. duplicateFile for folders now deep-clones children with new IDs and
   updated paths instead of copying by reference

2. updateChildrenPaths uses startsWith+slice instead of String.replace
   to avoid special replacement pattern issues and ensure prefix anchoring

Co-Authored-By: Thuong Huynh <admin@huynhthuong.online>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@Huynhthuongg Huynhthuongg marked this pull request as ready for review April 29, 2026 15:13
@Huynhthuongg Huynhthuongg merged commit f3412dd into main Apr 29, 2026
1 of 2 checks passed

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Pre-existing: dupName regex doesn't handle multi-dot filenames ideally

The dupName construction at line 502 uses /(\.\w+)$/ to split name from extension. For files like App.d.ts, this only captures the last extension segment (.ts), producing App.d (copy).ts instead of App (copy).d.ts. Similarly, for dotfiles like .gitignore, it strips the entire name to produce (copy).gitignore (note the leading space). This is a pre-existing issue not introduced by this PR, but worth noting since the duplicateFile function was modified.

(Refers to line 502)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

const updatedChild: FileNode = {
...child,
path: child.path.replace(oldPath, newPath),
path: child.path.startsWith(oldPath) ? newPath + child.path.slice(oldPath.length) : child.path,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: The updateChildrenPaths fix correctly addresses a real String.replace bug

The old code child.path.replace(oldPath, newPath) had two issues: (1) String.replace with a string pattern only replaces the first occurrence, which is fine for prefix replacement but semantically unclear; (2) more importantly, it could match oldPath as a substring at any position within child.path, not just at the start. For example, renaming a folder /a to /ab could incorrectly transform a child path /b/a/file to /b/ab/file if the old path appeared as a substring elsewhere. The new startsWith check is strictly correct.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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