plugin_path / command_path with ~ in config.yml creates stray directories in cwd
## Summary
When `plugin_path` or `command_path` are set to tilde-prefixed paths in `~/.config/doing/config.yml` (e.g. `"~/.config/doing/plugins"`), doing creates literal `~/.config/doing/` directory trees rooted at whatever the current working directory is when `doing` is invoked, rather than resolving them to the home directory.
## Version
doing 2.1.91
## Symptoms
Stray directories accumulate across the filesystem wherever `doing` is run. Each has the form:
```
<cwd>/~/.config/doing/
```
In my case I found these hollow `~` directories (each containing only `.config/doing/`) in:
- `~/` — created when doing was run from the home directory
- `~/ai/` — created when doing was run from that working directory
- `~/ai/retailer-distribution/` — same
- `~/dev/manager-bot/` — same
The directories contain no files — just the empty `doing/` folder structure. They accumulate silently over time.
## Root cause
`~/.config/doing/config.yml` ships (or is generated) with these lines:
```yaml
plugins:
plugin_path: "~/.config/doing/plugins"
command_path: "~/.config/doing/commands"
```
When this is read from YAML, `plugin_path` is a plain Ruby string — `~` is not expanded. It is passed directly to `FileUtils.mkdir_p` in `configuration.rb` (via `load_plugins`) without going through `File.expand_path`:
```ruby
# configuration.rb line 352
load_plugins(plugin_config['plugin_path'])
# configuration.rb line 536-539
def load_plugins(add_dir = nil)
FileUtils.mkdir_p(add_dir) if add_dir && !File.exist?(add_dir)
Plugins.load_plugins(add_dir)
end
```
`FileUtils.mkdir_p` does not expand `~`. It treats it as a literal directory name and creates it relative to the current directory.
The `DEFAULTS` hash in `configuration.rb` correctly uses `File.join(Util.user_home, '.config', 'doing', 'plugins')` — the expansion happens at load time and produces an absolute path. But once `plugin_path` appears in the user's config file as a tilde string, it overrides the safe default with an unexpanded one.
## Proposed fix
Add `File.expand_path` in `load_plugins` before passing the path to `FileUtils.mkdir_p`:
```ruby
def load_plugins(add_dir = nil)
add_dir = File.expand_path(add_dir) if add_dir
FileUtils.mkdir_p(add_dir) if add_dir && !File.exist?(add_dir)
Plugins.load_plugins(add_dir)
end
```
This is the minimal safe fix — it handles the case where a user's config has a tilde path without requiring any config migration.
A secondary improvement would be to expand paths when reading config values that are expected to be filesystem paths, so the issue can't recur for other path-type config keys.
## Workaround
Remove `plugin_path` and `command_path` from `~/.config/doing/config.yml`. The defaults in the gem use properly expanded absolute paths and work correctly.
关闭于 2026-04-14 1 条评论