diff --git a/docs/plugin-dev/plugin-yml-reference.md b/docs/plugin-dev/plugin-yml-reference.md index e6e8b341..ec2828a3 100644 --- a/docs/plugin-dev/plugin-yml-reference.md +++ b/docs/plugin-dev/plugin-yml-reference.md @@ -190,7 +190,9 @@ devbase 本体を更新してください (この警告を止める場合は DEV 同じ名前のプロジェクトを複数のPluginが提供したときに、どちらが `projects/` の シンボリックリンクを取るかを決める整数です(既定 `0`、大きいほうが勝ち)。 -負けた側は `projects/.--` の形でリンクされ、どちらも利用できます。 +負けた側は `projects/.----` の形でリンクされ、どちらも利用できます +(例: `projects/myapp.github.com--example-org--devbase-plugins`)。 +`--link` で入れた Plugin では、`.` の後ろがリンク元のパスの basename になります。 ```yaml priority: 10 diff --git a/lib/devbase/commands/project.py b/lib/devbase/commands/project.py index 3def91f5..096e526e 100644 --- a/lib/devbase/commands/project.py +++ b/lib/devbase/commands/project.py @@ -32,12 +32,12 @@ def _resolve_plugin_name(entry: Path) -> str | None: """projects/ 配下の entry が属する plugin 名を解決する。 entry が symlink の場合、その **リンク先** (``..//projects/``) - から plugin 名を解決する。PLAN04 の同名衝突 suffix (例 ``myapp.alice--myapp``) + から plugin 名を解決する。PLAN04 の同名衝突 suffix (例 ``myapp.github.com--example-org--devbase-plugins``) は **リンク名のみ** に付与され、リンク先 dir 名は素の ```` のままであるため、 リンク名でなくリンク先を辿ることで suffix の有無に関わらず正しく解決できる。 plugin 名はリンク先パスの ``projects`` セグメント直前の要素: - - repos ベース: ``../repos/--//projects/`` → ```` + - repos ベース: ``../repos/----//projects/`` → ```` - --link ベース: ``../plugins//projects/`` → ```` symlink でない実ディレクトリ (plugin に属さない) や解決不能な場合は ``None``。 diff --git a/lib/devbase/plugin/syncer.py b/lib/devbase/plugin/syncer.py index 04c8faf7..3e27fb6f 100644 --- a/lib/devbase/plugin/syncer.py +++ b/lib/devbase/plugin/syncer.py @@ -58,7 +58,8 @@ def discover_projects(plugin_dir: Path) -> list[str]: def _extract_owner(plugin: InstalledPlugin) -> str: """Extract a unique suffix identifier from a plugin for collision resolution. - For repos/-based plugins: full owner--repo dirname from repos/--/... + For repos/-based plugins: full dirname from repos/----/... + (e.g. github.com--example-org--devbase-plugins) This ensures uniqueness when the same owner has multiple repos. For --link plugins: basename of the source path """ @@ -67,7 +68,7 @@ def _extract_owner(plugin: InstalledPlugin) -> str: parts = Path(plugin.path).parts if len(parts) >= 2 and parts[0] == 'repos': - # Return full dir_name (owner--repo) to avoid collision + # Return full dir_name (host--owner--repo) to avoid collision # between repos from the same owner return parts[1] return plugin.name @@ -175,7 +176,7 @@ def sync_projects(registry: PluginRegistry, verbose: bool = True) -> int: """Synchronize project symlinks from all installed plugins. Creates symlinks in projects/ pointing to plugin directories: - - repos/-based plugins: projects/ -> ../repos/--//projects/ + - repos/-based plugins: projects/ -> ../repos/----//projects/ - --link plugins: projects/ -> ../plugins//projects/ On name collision, the winner (highest priority) gets the bare name,