dirsql 0.3.92__tar.gz → 0.3.94__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. {dirsql-0.3.92 → dirsql-0.3.94}/Cargo.lock +1 -1
  2. {dirsql-0.3.92 → dirsql-0.3.94}/PKG-INFO +1 -1
  3. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/_async.py +5 -4
  4. {dirsql-0.3.92/packages/rust → dirsql-0.3.94}/docs/reference/cli.md +1 -1
  5. {dirsql-0.3.92/packages/rust → dirsql-0.3.94}/docs/reference/config.md +5 -6
  6. {dirsql-0.3.92/packages/rust → dirsql-0.3.94}/docs/reference/sdk.md +8 -8
  7. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/Cargo.toml +1 -1
  8. {dirsql-0.3.92 → dirsql-0.3.94/packages/python}/docs/reference/cli.md +1 -1
  9. {dirsql-0.3.92 → dirsql-0.3.94/packages/python}/docs/reference/config.md +5 -6
  10. {dirsql-0.3.92 → dirsql-0.3.94/packages/python}/docs/reference/sdk.md +8 -8
  11. dirsql-0.3.94/packages/python/e2e-attestations/claude-open-issues-review-le8hm5-red-553.json +7 -0
  12. {dirsql-0.3.92/packages/python → dirsql-0.3.94/packages/rust}/docs/reference/cli.md +1 -1
  13. {dirsql-0.3.92/packages/python → dirsql-0.3.94/packages/rust}/docs/reference/config.md +5 -6
  14. {dirsql-0.3.92/packages/python → dirsql-0.3.94/packages/rust}/docs/reference/sdk.md +8 -8
  15. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/bin/dirsql.rs +7 -6
  16. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/config.rs +15 -84
  17. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/lib.rs +74 -74
  18. dirsql-0.3.92/packages/python/e2e-attestations/worktree-agent-a1a637f59ef70f352.json +0 -7
  19. {dirsql-0.3.92 → dirsql-0.3.94}/Cargo.toml +0 -0
  20. {dirsql-0.3.92 → dirsql-0.3.94}/README.md +0 -0
  21. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/__init__.py +0 -0
  22. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/_dirsql.pyi +0 -0
  23. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/cli/__init__.py +0 -0
  24. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/cli/binary_path.py +0 -0
  25. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/cli/is_windows.py +0 -0
  26. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/cli/main.py +0 -0
  27. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/cli/resolve_config_extensions.py +0 -0
  28. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/py.typed +0 -0
  29. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/resolve_config_extensions.py +0 -0
  30. {dirsql-0.3.92 → dirsql-0.3.94}/dirsql/resolve_extension.py +0 -0
  31. {dirsql-0.3.92 → dirsql-0.3.94}/docs/.claude/CLAUDE.md +0 -0
  32. {dirsql-0.3.92 → dirsql-0.3.94}/docs/.vitepress/config.ts +0 -0
  33. {dirsql-0.3.92 → dirsql-0.3.94}/docs/.vitepress/theme/index.ts +0 -0
  34. {dirsql-0.3.92 → dirsql-0.3.94}/docs/.vitepress/theme/lang.ts +0 -0
  35. {dirsql-0.3.92 → dirsql-0.3.94}/docs/AGENTS.md +0 -0
  36. {dirsql-0.3.92 → dirsql-0.3.94}/docs/explanation.md +0 -0
  37. {dirsql-0.3.92 → dirsql-0.3.94}/docs/getting-started.md +0 -0
  38. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/columns-from-paths.md +0 -0
  39. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/define-tables.md +0 -0
  40. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/embed.md +0 -0
  41. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/extract-from-contents.md +0 -0
  42. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/load-extension.md +0 -0
  43. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/persist.md +0 -0
  44. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/react-to-changes.md +0 -0
  45. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/search-by-meaning.md +0 -0
  46. {dirsql-0.3.92 → dirsql-0.3.94}/docs/howto/skip-files.md +0 -0
  47. {dirsql-0.3.92 → dirsql-0.3.94}/docs/index.md +0 -0
  48. {dirsql-0.3.92 → dirsql-0.3.94}/docs/migrations.md +0 -0
  49. {dirsql-0.3.92 → dirsql-0.3.94}/docs/package.json +0 -0
  50. {dirsql-0.3.92 → dirsql-0.3.94}/docs/playwright.config.ts +0 -0
  51. {dirsql-0.3.92 → dirsql-0.3.94}/docs/pnpm-lock.yaml +0 -0
  52. {dirsql-0.3.92 → dirsql-0.3.94}/docs/pnpm-workspace.yaml +0 -0
  53. {dirsql-0.3.92 → dirsql-0.3.94}/docs/reference/columns.md +0 -0
  54. {dirsql-0.3.92 → dirsql-0.3.94}/docs/reference/hooks.md +0 -0
  55. {dirsql-0.3.92 → dirsql-0.3.94}/docs/reference/http-api.md +0 -0
  56. {dirsql-0.3.92 → dirsql-0.3.94}/docs/tests/integration/home.spec.ts +0 -0
  57. {dirsql-0.3.92 → dirsql-0.3.94}/docs/tests/integration/language-flag.spec.ts +0 -0
  58. {dirsql-0.3.92 → dirsql-0.3.94}/docs/tests/integration/sidebar.spec.ts +0 -0
  59. {dirsql-0.3.92 → dirsql-0.3.94}/docs/tests/unit/config.test.ts +0 -0
  60. {dirsql-0.3.92 → dirsql-0.3.94}/docs/tests/unit/lang.test.ts +0 -0
  61. {dirsql-0.3.92 → dirsql-0.3.94}/docs/vitest.config.ts +0 -0
  62. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/README.md +0 -0
  63. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/conftest.py +0 -0
  64. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/.claude/CLAUDE.md +0 -0
  65. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/.vitepress/config.ts +0 -0
  66. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  67. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  68. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/AGENTS.md +0 -0
  69. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/explanation.md +0 -0
  70. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/getting-started.md +0 -0
  71. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/columns-from-paths.md +0 -0
  72. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/define-tables.md +0 -0
  73. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/embed.md +0 -0
  74. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/extract-from-contents.md +0 -0
  75. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/load-extension.md +0 -0
  76. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/persist.md +0 -0
  77. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/react-to-changes.md +0 -0
  78. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/search-by-meaning.md +0 -0
  79. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/howto/skip-files.md +0 -0
  80. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/index.md +0 -0
  81. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/migrations.md +0 -0
  82. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/package.json +0 -0
  83. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/playwright.config.ts +0 -0
  84. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/pnpm-lock.yaml +0 -0
  85. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/pnpm-workspace.yaml +0 -0
  86. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/reference/columns.md +0 -0
  87. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/reference/hooks.md +0 -0
  88. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/reference/http-api.md +0 -0
  89. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/tests/integration/home.spec.ts +0 -0
  90. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
  91. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
  92. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/tests/unit/config.test.ts +0 -0
  93. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/tests/unit/lang.test.ts +0 -0
  94. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/docs/vitest.config.ts +0 -0
  95. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/src/lib.rs +0 -0
  96. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/__init__.py +0 -0
  97. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/conftest.py +0 -0
  98. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/e2e/__init__.py +0 -0
  99. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/integration/__init__.py +0 -0
  100. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/integration/binding/__init__.py +0 -0
  101. {dirsql-0.3.92 → dirsql-0.3.94}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  102. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/Cargo.toml +0 -0
  103. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/README.md +0 -0
  104. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/benches/db_bench.rs +0 -0
  105. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/benches/differ_bench.rs +0 -0
  106. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/benches/matcher_bench.rs +0 -0
  107. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/benches/scanner_bench.rs +0 -0
  108. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/explanation.md +0 -0
  109. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/getting-started.md +0 -0
  110. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  111. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/define-tables.md +0 -0
  112. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/embed.md +0 -0
  113. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  114. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/load-extension.md +0 -0
  115. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/persist.md +0 -0
  116. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/react-to-changes.md +0 -0
  117. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  118. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/howto/skip-files.md +0 -0
  119. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/index.md +0 -0
  120. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/migrations.md +0 -0
  121. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/reference/columns.md +0 -0
  122. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/reference/hooks.md +0 -0
  123. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/docs/reference/http-api.md +0 -0
  124. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/execute.rs +0 -0
  125. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/init.rs +0 -0
  126. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/mod.rs +0 -0
  127. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/router.rs +0 -0
  128. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/serialize.rs +0 -0
  129. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/cli/server.rs +0 -0
  130. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/command.rs +0 -0
  131. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/db.rs +0 -0
  132. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/default_config.toml +0 -0
  133. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/differ.rs +0 -0
  134. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/matcher.rs +0 -0
  135. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/persist.rs +0 -0
  136. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/scanner.rs +0 -0
  137. {dirsql-0.3.92 → dirsql-0.3.94}/packages/rust/src/watcher.rs +0 -0
  138. {dirsql-0.3.92 → dirsql-0.3.94}/pyproject.toml +0 -0
@@ -500,7 +500,7 @@ dependencies = [
500
500
 
501
501
  [[package]]
502
502
  name = "dirsql-py-ext"
503
- version = "0.3.92"
503
+ version = "0.3.94"
504
504
  dependencies = [
505
505
  "dirsql",
506
506
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirsql
3
- Version: 0.3.92
3
+ Version: 0.3.94
4
4
  Summary: Ephemeral SQL index over a local directory
5
5
  Keywords: sql,filesystem,directory,sqlite,index
6
6
  Author: Kevin Scott
@@ -53,10 +53,11 @@ class DirSQL:
53
53
  async for event in db.watch():
54
54
  ...
55
55
 
56
- Supply a ``root``, a ``config`` path, or both. When both are set, the
57
- explicit ``root`` wins over any ``[dirsql].root`` in the config file (a
58
- warning is emitted on stderr). If neither is given, the initial scan
59
- fails with a "no root directory" error raised by the core.
56
+ The index root is the explicit ``root`` when given, else the process
57
+ current working directory. A ``config`` file's location never sets the
58
+ root -- it only supplies tables, ignore patterns, and extensions. There
59
+ is no ``[dirsql].root`` config key. Constructing with neither ``root``
60
+ nor ``config`` roots at the cwd (no error is raised).
60
61
 
61
62
  Pass ``persist=True`` to keep an on-disk SQLite cache (default location:
62
63
  ``<root>/.dirsql/cache.db``). Override the location with ``persist_path``.
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
45
45
 
46
46
  | Flag | Default | Description |
47
47
  |---|---|---|
48
- | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
48
+ | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is always rooted at the **invocation directory** (the current working directory), regardless of where this file lives so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
49
49
  | `--host <addr>` | `localhost` | Bind address. |
50
50
  | `--port <n>` | `7117` | TCP port to bind. |
51
51
  | `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
@@ -11,16 +11,16 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
11
11
  overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
12
12
  parameter.
13
13
 
14
- **Path resolution.** Relative paths in the config (`root`,
15
- `[[dirsql.extension]]` `path`) resolve against the config file's parent
16
- directory. The scan root defaults to that same directory when `root` is not
17
- set.
14
+ **Path resolution.** Relative paths in the config (`[[dirsql.extension]]`
15
+ `path`) resolve against the config file's parent
16
+ directory. The **index root is not a config concern** it is decided by the
17
+ runner (the CLI's invocation directory, or an SDK's explicit root), never by
18
+ the config file's location. See [`--config`](./cli.md#flags).
18
19
 
19
20
  ## `[dirsql]` keys
20
21
 
21
22
  | Key | Type | Default | Description |
22
23
  |---|---|---|---|
23
- | `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
24
24
  | `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
25
25
  | `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
26
26
  | `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
@@ -34,7 +34,6 @@ directory.
34
34
 
35
35
  ```toml
36
36
  [dirsql]
37
- root = "../data"
38
37
  ignore = ["node_modules/**", ".git/**"]
39
38
  hook-timeout = 300
40
39
  ```
@@ -92,22 +92,22 @@ DirSQL::builder()
92
92
 
93
93
  :::
94
94
 
95
- Creates a SQLite index over a directory. At least one of `root` or `config`
96
- must be supplied; with neither, construction fails with a "no root
97
- directory" error.
95
+ Creates a SQLite index over a directory. The index root is the explicit
96
+ `root` when given, else the **process cwd** the `config` file's location
97
+ never sets the root.
98
98
 
99
99
  **Parameters:**
100
100
 
101
- - `root` — Directory to index. Optional if `config` is supplied.
101
+ - `root` — Directory to index. When omitted, the index roots at the process
102
+ cwd (even when `config` is supplied).
102
103
  - `tables` — Programmatic [`Table`](#table) definitions.
103
104
  - `ignore` — Glob patterns matched against root-relative paths; matched
104
105
  files are skipped entirely (scan and watch).
105
106
  - `config` — Path to a [`.dirsql.toml`](./config.md). Its `[[table]]`
106
107
  entries are appended after any programmatic `tables`; its `ignore`
107
- patterns and `[[dirsql.extension]]` entries are appended likewise; its
108
- `[dirsql].root` supplies the root when no explicit `root` is passed.
109
- When both an explicit `root` and a config root are present, the explicit
110
- value wins and a warning is emitted on stderr.
108
+ patterns and `[[dirsql.extension]]` entries are appended likewise. The
109
+ config file does **not** set the index root: with no explicit `root`, the
110
+ index roots at the process cwd.
111
111
  - `persist` — Keep the SQLite index on disk between runs (default off:
112
112
  ephemeral, rebuilt every startup). The cache lives at
113
113
  `<root>/.dirsql/cache.db` by default; on restart, only files whose stat
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
4
4
  # pypi/maturin handler can rewrite it via `write-version` before
5
5
  # `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
6
6
  # and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
7
- version = "0.3.92"
7
+ version = "0.3.94"
8
8
  # abi3 note: the `abi3-py311` pyo3 feature (below) builds ONE stable-ABI
9
9
  # `cp311-abi3` wheel per platform that loads on every CPython >= 3.11
10
10
  # (matching `pyproject.toml`'s `requires-python = ">=3.11"`), instead of
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
45
45
 
46
46
  | Flag | Default | Description |
47
47
  |---|---|---|
48
- | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
48
+ | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is always rooted at the **invocation directory** (the current working directory), regardless of where this file lives so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
49
49
  | `--host <addr>` | `localhost` | Bind address. |
50
50
  | `--port <n>` | `7117` | TCP port to bind. |
51
51
  | `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
@@ -11,16 +11,16 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
11
11
  overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
12
12
  parameter.
13
13
 
14
- **Path resolution.** Relative paths in the config (`root`,
15
- `[[dirsql.extension]]` `path`) resolve against the config file's parent
16
- directory. The scan root defaults to that same directory when `root` is not
17
- set.
14
+ **Path resolution.** Relative paths in the config (`[[dirsql.extension]]`
15
+ `path`) resolve against the config file's parent
16
+ directory. The **index root is not a config concern** it is decided by the
17
+ runner (the CLI's invocation directory, or an SDK's explicit root), never by
18
+ the config file's location. See [`--config`](./cli.md#flags).
18
19
 
19
20
  ## `[dirsql]` keys
20
21
 
21
22
  | Key | Type | Default | Description |
22
23
  |---|---|---|---|
23
- | `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
24
24
  | `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
25
25
  | `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
26
26
  | `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
@@ -34,7 +34,6 @@ directory.
34
34
 
35
35
  ```toml
36
36
  [dirsql]
37
- root = "../data"
38
37
  ignore = ["node_modules/**", ".git/**"]
39
38
  hook-timeout = 300
40
39
  ```
@@ -92,22 +92,22 @@ DirSQL::builder()
92
92
 
93
93
  :::
94
94
 
95
- Creates a SQLite index over a directory. At least one of `root` or `config`
96
- must be supplied; with neither, construction fails with a "no root
97
- directory" error.
95
+ Creates a SQLite index over a directory. The index root is the explicit
96
+ `root` when given, else the **process cwd** the `config` file's location
97
+ never sets the root.
98
98
 
99
99
  **Parameters:**
100
100
 
101
- - `root` — Directory to index. Optional if `config` is supplied.
101
+ - `root` — Directory to index. When omitted, the index roots at the process
102
+ cwd (even when `config` is supplied).
102
103
  - `tables` — Programmatic [`Table`](#table) definitions.
103
104
  - `ignore` — Glob patterns matched against root-relative paths; matched
104
105
  files are skipped entirely (scan and watch).
105
106
  - `config` — Path to a [`.dirsql.toml`](./config.md). Its `[[table]]`
106
107
  entries are appended after any programmatic `tables`; its `ignore`
107
- patterns and `[[dirsql.extension]]` entries are appended likewise; its
108
- `[dirsql].root` supplies the root when no explicit `root` is passed.
109
- When both an explicit `root` and a config root are present, the explicit
110
- value wins and a warning is emitted on stderr.
108
+ patterns and `[[dirsql.extension]]` entries are appended likewise. The
109
+ config file does **not** set the index root: with no explicit `root`, the
110
+ index roots at the process cwd.
111
111
  - `persist` — Keep the SQLite index on disk between runs (default off:
112
112
  ephemeral, rebuilt every startup). The cache lives at
113
113
  `<root>/.dirsql/cache.db` by default; on restart, only files whose stat
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/ -x -q",
3
+ "ran_at": 1783941005,
4
+ "exit_code": 0,
5
+ "commit": "08325768e4fc2cae5e67e98a1d1e2d40e75f4afb",
6
+ "branch": "claude/open-issues-review-le8hm5-red-553"
7
+ }
@@ -45,7 +45,7 @@ requests, closes open `/events` streams, and exits.
45
45
 
46
46
  | Flag | Default | Description |
47
47
  |---|---|---|
48
- | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is rooted at the directory containing this file (unless the config sets `[dirsql].root`). When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
48
+ | `-c, --config <path>` | `./.dirsql.toml` | Path to the [config file](./config.md). The index is always rooted at the **invocation directory** (the current working directory), regardless of where this file lives so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql` from. When the file does not exist, the server runs in [zero-config mode](#zero-config-mode). |
49
49
  | `--host <addr>` | `localhost` | Bind address. |
50
50
  | `--port <n>` | `7117` | TCP port to bind. |
51
51
  | `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Global — also honored by [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
@@ -11,16 +11,16 @@ The [CLI](./cli.md) loads `./.dirsql.toml` by default (`--config <path>`
11
11
  overrides). The [SDKs](./sdk.md) load a config via the `config` constructor
12
12
  parameter.
13
13
 
14
- **Path resolution.** Relative paths in the config (`root`,
15
- `[[dirsql.extension]]` `path`) resolve against the config file's parent
16
- directory. The scan root defaults to that same directory when `root` is not
17
- set.
14
+ **Path resolution.** Relative paths in the config (`[[dirsql.extension]]`
15
+ `path`) resolve against the config file's parent
16
+ directory. The **index root is not a config concern** it is decided by the
17
+ runner (the CLI's invocation directory, or an SDK's explicit root), never by
18
+ the config file's location. See [`--config`](./cli.md#flags).
18
19
 
19
20
  ## `[dirsql]` keys
20
21
 
21
22
  | Key | Type | Default | Description |
22
23
  |---|---|---|---|
23
- | `root` | string | config file's parent directory | Directory to index. Relative values resolve against the config file's parent. An explicit `root` passed to an SDK constructor overrides this (a warning is emitted on stderr). |
24
24
  | `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
25
25
  | `pre-query` | string | none | Server-wide command hook: the raw `POST /query` request body is passed to this command as `{args}`, and the plain-text SQL it prints is executed instead of parsing the body as `{"sql": …}`. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#pre-query). |
26
26
  | `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
@@ -34,7 +34,6 @@ directory.
34
34
 
35
35
  ```toml
36
36
  [dirsql]
37
- root = "../data"
38
37
  ignore = ["node_modules/**", ".git/**"]
39
38
  hook-timeout = 300
40
39
  ```
@@ -92,22 +92,22 @@ DirSQL::builder()
92
92
 
93
93
  :::
94
94
 
95
- Creates a SQLite index over a directory. At least one of `root` or `config`
96
- must be supplied; with neither, construction fails with a "no root
97
- directory" error.
95
+ Creates a SQLite index over a directory. The index root is the explicit
96
+ `root` when given, else the **process cwd** the `config` file's location
97
+ never sets the root.
98
98
 
99
99
  **Parameters:**
100
100
 
101
- - `root` — Directory to index. Optional if `config` is supplied.
101
+ - `root` — Directory to index. When omitted, the index roots at the process
102
+ cwd (even when `config` is supplied).
102
103
  - `tables` — Programmatic [`Table`](#table) definitions.
103
104
  - `ignore` — Glob patterns matched against root-relative paths; matched
104
105
  files are skipped entirely (scan and watch).
105
106
  - `config` — Path to a [`.dirsql.toml`](./config.md). Its `[[table]]`
106
107
  entries are appended after any programmatic `tables`; its `ignore`
107
- patterns and `[[dirsql.extension]]` entries are appended likewise; its
108
- `[dirsql].root` supplies the root when no explicit `root` is passed.
109
- When both an explicit `root` and a config root are present, the explicit
110
- value wins and a warning is emitted on stderr.
108
+ patterns and `[[dirsql.extension]]` entries are appended likewise. The
109
+ config file does **not** set the index root: with no explicit `root`, the
110
+ index roots at the process cwd.
111
111
  - `persist` — Keep the SQLite index on disk between runs (default off:
112
112
  ephemeral, rebuilt every startup). The cache lives at
113
113
  `<root>/.dirsql/cache.db` by default; on restart, only files whose stat
@@ -34,9 +34,9 @@ struct Cli {
34
34
  command: Option<Command>,
35
35
 
36
36
  /// Path to the config file (default: `./.dirsql.toml`). The index is
37
- /// rooted at the directory containing this file. When the file does
38
- /// not exist, a default `files` table is served. Used by server mode
39
- /// and by the `query` subcommand.
37
+ /// rooted at the invocation directory (cwd), not this file's location
38
+ /// (#540). When the file does not exist, a default `files` table is
39
+ /// served. Used by server mode and by the `query` subcommand.
40
40
  #[arg(short = 'c', long, default_value = "./.dirsql.toml", global = true)]
41
41
  config: PathBuf,
42
42
 
@@ -238,9 +238,10 @@ fn load_state(cli: &Cli) -> AppState {
238
238
  return load_default_state(cli, config_path);
239
239
  }
240
240
 
241
- // Canonicalize so the root (derived from the config's parent) is
242
- // absolute — `notify` has surprising behavior when watching relative
243
- // paths like `./`.
241
+ // Canonicalize so config-relative paths (extension libraries, hook
242
+ // working directories) resolve against an absolute parent — `notify` and
243
+ // the hook subprocesses misbehave with relative paths like `./`. The
244
+ // index root itself is the invocation cwd (#540), not derived from here.
244
245
  let resolved = match config_path.canonicalize() {
245
246
  Ok(p) => p,
246
247
  Err(err) => {
@@ -68,16 +68,13 @@ impl std::fmt::Display for Source {
68
68
  /// Order-significant; at least one entry is required and a single entry is
69
69
  /// returned unchanged. List-shaped config (`[[table]]`, `[[dirsql.extension]]`,
70
70
  /// `ignore`) concatenates in input order. A table-name collision anywhere in
71
- /// the combined set errors, naming both sources. Single-valued keys (`root`,
72
- /// `pre-query`, `post-query`, `hook-timeout`) defined by more than
71
+ /// the combined set errors, naming both sources. Single-valued keys
72
+ /// (`pre-query`, `post-query`, `hook-timeout`) defined by more than
73
73
  /// one config error, naming both sources — no silent shadowing, no precedence;
74
74
  /// defined in exactly one config they merge through unchanged.
75
75
  ///
76
76
  /// Tables whose DDL yields no parseable table name are concatenated without a
77
77
  /// collision check; `Db::create_table` rejects them downstream.
78
- ///
79
- /// Plugin whitelist enforcement ("a fragment may not set `root`") is the
80
- /// discovery layer's job, per fragment, before calling this.
81
78
  pub fn combine_configs(configs: &[(Source, Config)]) -> Result<Config> {
82
79
  let (first, rest) = configs.split_first().ok_or(ConfigError::NoConfigs)?;
83
80
  if rest.is_empty() {
@@ -90,7 +87,6 @@ pub fn combine_configs(configs: &[(Source, Config)]) -> Result<Config> {
90
87
  let mut table_sources: std::collections::HashMap<String, &Source> =
91
88
  std::collections::HashMap::new();
92
89
 
93
- let mut root: Option<(&Source, PathBuf)> = None;
94
90
  let mut pre_query: Option<(&Source, String)> = None;
95
91
  let mut post_query: Option<(&Source, String)> = None;
96
92
  let mut hook_timeout: Option<(&Source, Duration)> = None;
@@ -111,7 +107,6 @@ pub fn combine_configs(configs: &[(Source, Config)]) -> Result<Config> {
111
107
  ignore.extend(config.ignore.iter().cloned());
112
108
  extensions.extend(config.extensions.iter().cloned());
113
109
 
114
- merge_single("root", &mut root, config.root.as_ref(), source)?;
115
110
  merge_single(
116
111
  "pre-query",
117
112
  &mut pre_query,
@@ -133,7 +128,6 @@ pub fn combine_configs(configs: &[(Source, Config)]) -> Result<Config> {
133
128
  }
134
129
 
135
130
  Ok(Config {
136
- root: root.map(|(_, value)| value),
137
131
  ignore,
138
132
  tables,
139
133
  extensions,
@@ -167,11 +161,6 @@ fn merge_single<'a, T: Clone>(
167
161
  /// Parsed configuration from a `.dirsql.toml` file.
168
162
  #[derive(Debug, Clone)]
169
163
  pub struct Config {
170
- /// Optional root directory override. When absent, callers derive the
171
- /// root from the config file's own location. When present, it is taken
172
- /// relative to the config file's parent (so a config at
173
- /// `/proj/.dirsql.toml` with `root = "docs"` scans `/proj/docs`).
174
- pub root: Option<PathBuf>,
175
164
  pub ignore: Vec<String>,
176
165
  pub tables: Vec<TableConfig>,
177
166
  /// SQLite extensions to load at startup, declared via
@@ -249,7 +238,6 @@ struct RawConfig {
249
238
  #[derive(Deserialize, Default)]
250
239
  #[serde(deny_unknown_fields)]
251
240
  struct RawDirsql {
252
- root: Option<PathBuf>,
253
241
  ignore: Option<Vec<String>>,
254
242
  extension: Option<Vec<RawExtension>>,
255
243
  #[serde(rename = "pre-query")]
@@ -288,7 +276,6 @@ pub fn load_config_str(content: &str) -> Result<Config> {
288
276
  let raw: RawConfig = toml::from_str(content)?;
289
277
 
290
278
  let d = raw.dirsql.unwrap_or_default();
291
- let root = d.root;
292
279
  let ignore = d.ignore.unwrap_or_default();
293
280
  let raw_extensions = d.extension.unwrap_or_default();
294
281
  let raw_pre_query = d.pre_query;
@@ -348,7 +335,6 @@ pub fn load_config_str(content: &str) -> Result<Config> {
348
335
  }
349
336
 
350
337
  Ok(Config {
351
- root,
352
338
  ignore,
353
339
  tables,
354
340
  extensions,
@@ -463,45 +449,6 @@ glob = "*.json"
463
449
  assert!(matches!(err, ConfigError::Io(_)), "got: {err:?}");
464
450
  }
465
451
 
466
- #[test]
467
- fn optional_root_parses_when_present() {
468
- let toml = r#"
469
- [dirsql]
470
- root = "docs"
471
-
472
- [[table]]
473
- ddl = "CREATE TABLE t (path TEXT)"
474
- glob = "*.json"
475
- "#;
476
- let config = load_config_str(toml).unwrap();
477
- assert_eq!(config.root.as_deref(), Some(Path::new("docs")));
478
- }
479
-
480
- #[test]
481
- fn root_absent_by_default() {
482
- let toml = r#"
483
- [[table]]
484
- ddl = "CREATE TABLE t (path TEXT)"
485
- glob = "*.json"
486
- "#;
487
- let config = load_config_str(toml).unwrap();
488
- assert!(config.root.is_none());
489
- }
490
-
491
- #[test]
492
- fn root_can_be_absolute() {
493
- let toml = r#"
494
- [dirsql]
495
- root = "/tmp/data"
496
-
497
- [[table]]
498
- ddl = "CREATE TABLE t (path TEXT)"
499
- glob = "*.json"
500
- "#;
501
- let config = load_config_str(toml).unwrap();
502
- assert_eq!(config.root.as_deref(), Some(Path::new("/tmp/data")));
503
- }
504
-
505
452
  #[test]
506
453
  fn persist_key_is_rejected_as_unknown() {
507
454
  // Persistence moved to the `--persist` CLI flag; the TOML key is gone.
@@ -585,6 +532,19 @@ glbo = "typo"
585
532
  assert!(err.to_string().contains("glbo"), "got: {err}");
586
533
  }
587
534
 
535
+ #[test]
536
+ fn root_key_in_dirsql_section_is_rejected() {
537
+ // `root` is no longer a config key (#540): the runner owns the index
538
+ // root. An old config carrying it fails loudly, naming the key.
539
+ let toml = r#"
540
+ [dirsql]
541
+ root = "docs"
542
+ "#;
543
+ let err = load_config_str(toml).unwrap_err();
544
+ assert!(matches!(err, ConfigError::Toml(_)), "got: {err:?}");
545
+ assert!(err.to_string().contains("root"), "got: {err}");
546
+ }
547
+
588
548
  #[test]
589
549
  fn unknown_key_in_extension_is_rejected() {
590
550
  // A misspelled `[[dirsql.extension]]` key (`entrypont`) errors.
@@ -807,7 +767,6 @@ post-query = " "
807
767
  fn combine_singleton_returns_config_unchanged() {
808
768
  let config = cfg(r#"
809
769
  [dirsql]
810
- root = "docs"
811
770
  ignore = ["*.tmp"]
812
771
  pre-query = "to_sql {args}"
813
772
  post-query = "jq '{results: .}'"
@@ -821,7 +780,6 @@ ddl = "CREATE TABLE t (path TEXT)"
821
780
  glob = "*.json"
822
781
  "#);
823
782
  let merged = combine_configs(&[(src("/proj/.dirsql.toml"), config.clone())]).unwrap();
824
- assert_eq!(merged.root, config.root);
825
783
  assert_eq!(merged.ignore, config.ignore);
826
784
  assert_eq!(merged.extensions, config.extensions);
827
785
  assert_eq!(merged.pre_query, config.pre_query);
@@ -1007,33 +965,6 @@ glob = "c/*.json"
1007
965
  assert_eq!(merged.post_query.as_deref(), Some("jq -c ."));
1008
966
  }
1009
967
 
1010
- #[test]
1011
- fn combine_root_in_two_configs_errors_naming_both_sources() {
1012
- let a = cfg("[dirsql]\nroot = \"docs\"\n");
1013
- let b = cfg("[dirsql]\nroot = \"data\"\n");
1014
- let err = combine_configs(&[(src("/a"), a), (src("/b"), b)]).unwrap_err();
1015
- match &err {
1016
- ConfigError::ConflictingKey { key, first, second } => {
1017
- assert_eq!(*key, "root");
1018
- assert_eq!(first, &src("/a"));
1019
- assert_eq!(second, &src("/b"));
1020
- }
1021
- other => panic!("got: {other:?}"),
1022
- }
1023
- let msg = err.to_string();
1024
- assert!(msg.contains("'root'"), "got: {msg}");
1025
- assert!(msg.contains("/a"), "got: {msg}");
1026
- assert!(msg.contains("/b"), "got: {msg}");
1027
- }
1028
-
1029
- #[test]
1030
- fn combine_root_in_one_config_merges_through() {
1031
- let a = cfg("[dirsql]\nignore = [\"a/**\"]\n");
1032
- let b = cfg("[dirsql]\nroot = \"docs\"\n");
1033
- let merged = combine_configs(&[(src("/a"), a), (src("/b"), b)]).unwrap();
1034
- assert_eq!(merged.root.as_deref(), Some(Path::new("docs")));
1035
- }
1036
-
1037
968
  #[test]
1038
969
  fn combine_error_display_includes_package_source_verbatim() {
1039
970
  let a = cfg("[[table]]\nddl = \"CREATE TABLE t (x TEXT)\"\nglob = \"a/*.json\"\n");