Skip to content

ENG-1652 Add .dg.metadata for stable import folder identification#970

Open
trangdoan982 wants to merge 5 commits intomainfrom
eng-1652-adding-source-vault-identifier-metadata-to-imported-folder
Open

ENG-1652 Add .dg.metadata for stable import folder identification#970
trangdoan982 wants to merge 5 commits intomainfrom
eng-1652-adding-source-vault-identifier-metadata-to-imported-folder

Conversation

@trangdoan982
Copy link
Copy Markdown
Member

@trangdoan982 trangdoan982 commented Apr 18, 2026

https://www.loom.com/share/eb8d0f513e0148bda7ee6bef730735cc

Summary

  • Replaces vault-name-based import folder matching with spaceUri-based matching, fixing issues with vault renames and vault name collisions
  • Each imported folder gets a .dg.metadata file containing spaceUri, spaceName, and optional userName
  • Adds one-time migration on onLoad to backfill .dg.metadata for existing import folders using plugin.settings.spaceNames

Changes

  • New importFolderMetadata.ts: utility functions to read/write .dg.metadata, build a spaceUri → folderPath map by scanning import/, and resolve folders by spaceUri with name-based fallback and collision-safe folder creation (import/MyVault-{shortId}/)
  • importSelectedNodes: uses resolveFolderForSpaceUri instead of constructing import/${sanitizedSpaceName} directly; handles folder creation and metadata writing
  • importAssetsForNode: accepts already-resolved importBasePath instead of recomputing from spaceName
  • index.ts: calls migrateImportFolderMetadata in onLoad
  • ImportNodesModal.tsx: stops writing new entries to plugin.settings.spaceNames (reads kept for migration path)

Test plan

  • Import a vault → confirm .dg.metadata is written inside import/<vaultName>/
  • Rename source vault in DB → re-import → confirm files go into the existing folder, not a new one
  • Manually rename the imported folder → re-import → confirm scan still finds it by spaceUri

Closes ENG-1652

🤖 Generated with Claude Code


Open with Devin

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]>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented Apr 18, 2026

@supabase
Copy link
Copy Markdown

supabase Bot commented Apr 18, 2026

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

devin-ai-integration[bot]

This comment was marked as resolved.

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]>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Collaborator

@maparent maparent left a comment

Choose a reason for hiding this comment

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

Overall look goods, two small changes.

Comment thread apps/obsidian/src/utils/importNodes.ts Outdated
Comment thread apps/obsidian/src/utils/importFolderMetadata.ts Outdated
@trangdoan982 trangdoan982 removed the request for review from mdroidian April 27, 2026 20:55
@trangdoan982 trangdoan982 requested a review from maparent April 27, 2026 21:01
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

View 13 additional findings in Devin Review.

Open in Devin Review

Comment on lines +201 to +204
const nameToSpaceUri = new Map<string, string>();
for (const [spaceUri, name] of Object.entries(spaceNames)) {
nameToSpaceUri.set(sanitizeFileName(name), spaceUri);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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.
Open in Devin Review

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()}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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.

Suggested change
newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`;
newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`;
while (await adapter.exists(newPath)) {
newPath = `${IMPORT_ROOT}/${sanitized}-${generateShortId()}`;
}
Open in Devin Review

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

Copy link
Copy Markdown
Collaborator

@maparent maparent left a comment

Choose a reason for hiding this comment

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

LGTM

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.

2 participants