ENG-1652 Add .dg.metadata for stable import folder identification#970
ENG-1652 Add .dg.metadata for stable import folder identification#970trangdoan982 wants to merge 5 commits intomainfrom
Conversation
Replace vault-name-based folder matching with spaceUri-based matching to
handle vault renames and name collisions. Each imported folder now gets a
.dg.metadata file with spaceUri, spaceName, and optional userName fields.
- New importFolderMetadata.ts utility: read/write .dg.metadata, build
spaceUri→folderPath map, resolve folders by spaceUri with name-based
fallback and collision-safe folder creation
- Migration on onLoad backfills .dg.metadata for existing folders using
plugin.settings.spaceNames as the source of truth
- importSelectedNodes uses resolveFolderForSpaceUri instead of naive
import/${sanitizedSpaceName} path construction
- Stop writing to plugin.settings.spaceNames (reads kept for migration)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
UI components (NodeTypeSettings, RelationshipTypeSettings, etc.) read plugin.settings.spaceNames via formatImportSource() to display human-readable vault names. Restore the write so new imports don't show truncated vault IDs. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
maparent
left a comment
There was a problem hiding this comment.
Overall look goods, two small changes.
| const nameToSpaceUri = new Map<string, string>(); | ||
| for (const [spaceUri, name] of Object.entries(spaceNames)) { | ||
| nameToSpaceUri.set(sanitizeFileName(name), spaceUri); | ||
| } |
There was a problem hiding this comment.
🟡 Migration silently assigns wrong spaceUri when multiple spaces share the same sanitized name
In migrateImportFolderMetadata, the nameToSpaceUri map is built by iterating Object.entries(spaceNames) and keying on sanitizeFileName(name). If two different spaceUris map to the same sanitized name (e.g., "obsidian:abc" → "My Space" and "obsidian:def" → "My Space"), the last entry silently overwrites the first. The import folder then gets tagged with the wrong spaceUri. Future imports from the overwritten spaceUri will fail to match the existing folder (step 1 of resolveFolderForSpaceUri at importFolderMetadata.ts:125) and will create a new folder (step 3), leaving old imported files in a folder tagged with a different space's URI.
Possible fix: detect collisions and skip ambiguous folders
Before assigning metadata, check if the sanitized name has already been used. If a collision is detected in the inverted map, skip migration for that folder and log a warning, rather than silently assigning the wrong URI.
Prompt for agents
In migrateImportFolderMetadata, the nameToSpaceUri Map is built from Object.entries(spaceNames), keying on sanitizeFileName(name). When two different spaceUris map to the same sanitized name, only the last one survives in the Map, causing the folder to be tagged with the wrong spaceUri.
To fix this: when building the nameToSpaceUri Map (lines 201-204 in importFolderMetadata.ts), detect collisions. If a sanitized name is already present in the Map, either:
1. Remove that key from the Map entirely (skip ambiguous migrations), or
2. Store a Set of spaceUris per name, and in the folder-matching loop (line 212), only write metadata when the mapping is unambiguous (Set has exactly one entry).
A log warning when a collision is detected would help users diagnose the issue.
Was this helpful? React with 👍 or 👎 to provide feedback.
| let newPath: string; | ||
| if (desiredExists) { | ||
| // The existing folder has a different spaceUri (would have been returned above otherwise) | ||
| newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`; |
There was a problem hiding this comment.
🟡 No existence check for randomly generated collision-avoidance folder path
When resolveFolderForSpaceUri detects a name collision at step 3 (line 169), it appends a random 6-char suffix via generateShortId() but never checks whether the resulting path already exists. While the collision probability is very low (~1 in 2.2 billion), if a collision occurs, adapter.mkdir may be a no-op on an existing folder, and writeImportFolderMetadata at line 180 would overwrite that folder's .dg.metadata, effectively stealing it from another space.
| newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`; | |
| newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`; | |
| while (await adapter.exists(newPath)) { | |
| newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`; | |
| } |
Was this helpful? React with 👍 or 👎 to provide feedback.
https://www.loom.com/share/eb8d0f513e0148bda7ee6bef730735cc
Summary
spaceUri-based matching, fixing issues with vault renames and vault name collisions.dg.metadatafile containingspaceUri,spaceName, and optionaluserNameonLoadto backfill.dg.metadatafor existing import folders usingplugin.settings.spaceNamesChanges
importFolderMetadata.ts: utility functions to read/write.dg.metadata, build aspaceUri → folderPathmap by scanningimport/, and resolve folders byspaceUriwith name-based fallback and collision-safe folder creation (import/MyVault-{shortId}/)importSelectedNodes: usesresolveFolderForSpaceUriinstead of constructingimport/${sanitizedSpaceName}directly; handles folder creation and metadata writingimportAssetsForNode: accepts already-resolvedimportBasePathinstead of recomputing fromspaceNameindex.ts: callsmigrateImportFolderMetadatainonLoadImportNodesModal.tsx: stops writing new entries toplugin.settings.spaceNames(reads kept for migration path)Test plan
.dg.metadatais written insideimport/<vaultName>/spaceUriCloses ENG-1652
🤖 Generated with Claude Code