dirsql 0.4.59__tar.gz → 0.4.60__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.
- {dirsql-0.4.59 → dirsql-0.4.60}/Cargo.lock +2 -2
- {dirsql-0.4.59 → dirsql-0.4.60}/PKG-INFO +1 -1
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/Cargo.toml +1 -1
- dirsql-0.4.60/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +7 -0
- dirsql-0.4.60/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +7 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/Cargo.toml +1 -1
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/command.rs +254 -2
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/extension_resolution.rs +5 -1
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/lib.rs +25 -4
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/parsed_vtab.rs +2 -2
- {dirsql-0.4.59 → dirsql-0.4.60}/Cargo.toml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/README.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/_async.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/plan_entry_path.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/py.typed +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/read_config.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/AGENTS.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/explanation.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/getting-started.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/embed.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/persist.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/index.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/package.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/plugins.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/cli.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/README.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/conftest.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/e2e/speed_of_light.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/README.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/parsed_cache.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/progress.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/row_event_flat.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/vtab_scaffold.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.59 → dirsql-0.4.60}/pyproject.toml +0 -0
|
@@ -552,7 +552,7 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
|
|
552
552
|
|
|
553
553
|
[[package]]
|
|
554
554
|
name = "dirsql"
|
|
555
|
-
version = "0.4.
|
|
555
|
+
version = "0.4.60"
|
|
556
556
|
dependencies = [
|
|
557
557
|
"assert_cmd",
|
|
558
558
|
"axum",
|
|
@@ -601,7 +601,7 @@ dependencies = [
|
|
|
601
601
|
|
|
602
602
|
[[package]]
|
|
603
603
|
name = "dirsql-py-ext"
|
|
604
|
-
version = "0.4.
|
|
604
|
+
version = "0.4.60"
|
|
605
605
|
dependencies = [
|
|
606
606
|
"dirsql",
|
|
607
607
|
"pyo3",
|
|
@@ -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.4.
|
|
7
|
+
version = "0.4.60"
|
|
8
8
|
# abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
|
|
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
|
|
|
6
6
|
# version stays for the binding crates (publish = false). The literal
|
|
7
7
|
# intentionally lags the published version: putitoutthere rewrites it to
|
|
8
8
|
# the planned release version at build time and never commits it back.
|
|
9
|
-
version = "0.4.
|
|
9
|
+
version = "0.4.60"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -49,6 +49,63 @@ impl Placeholder {
|
|
|
49
49
|
value: value.into(),
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
/// A placeholder whose value is a filesystem path, handed to the child in
|
|
54
|
+
/// its plain (non-verbatim) form; see [`non_verbatim`].
|
|
55
|
+
pub fn path(name: impl Into<String>, path: &str) -> Self {
|
|
56
|
+
Self::new(name, non_verbatim(path))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// The plain form of a Windows verbatim path: `\\?\C:\x` becomes `C:\x` and
|
|
61
|
+
/// `\\?\UNC\server\share\x` becomes `\\server\share\x`. Anything else, and any
|
|
62
|
+
/// verbatim path whose plain spelling would name a different file, is returned
|
|
63
|
+
/// unchanged.
|
|
64
|
+
pub(crate) fn non_verbatim(path: &str) -> String {
|
|
65
|
+
plain_form(path).unwrap_or_else(|| path.to_string())
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn plain_form(path: &str) -> Option<String> {
|
|
69
|
+
let rest = path.strip_prefix(r"\\?\")?;
|
|
70
|
+
let (plain, tail) = if let Some(unc) = rest.strip_prefix(r"UNC\") {
|
|
71
|
+
if unc.split('\\').count() < 2 {
|
|
72
|
+
return None;
|
|
73
|
+
}
|
|
74
|
+
(format!(r"\\{unc}"), unc)
|
|
75
|
+
} else {
|
|
76
|
+
let drive = rest.as_bytes();
|
|
77
|
+
let is_drive = drive.len() >= 3
|
|
78
|
+
&& drive[0].is_ascii_alphabetic()
|
|
79
|
+
&& drive[1] == b':'
|
|
80
|
+
&& drive[2] == b'\\';
|
|
81
|
+
if !is_drive {
|
|
82
|
+
return None;
|
|
83
|
+
}
|
|
84
|
+
(rest.to_string(), &rest[3..])
|
|
85
|
+
};
|
|
86
|
+
// Win32 rejects or rewrites these, so the plain spelling would not name
|
|
87
|
+
// the same file; MAX_PATH counts UTF-16 units including the terminator.
|
|
88
|
+
let same_file = (tail.is_empty() || tail.split('\\').all(is_plain_component))
|
|
89
|
+
&& plain.encode_utf16().count() < 260;
|
|
90
|
+
same_file.then_some(plain)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fn is_plain_component(name: &str) -> bool {
|
|
94
|
+
let invalid_char = |c: char| c < ' ' || r#"/<>:"|?*"#.contains(c);
|
|
95
|
+
let stem = name
|
|
96
|
+
.split_once('.')
|
|
97
|
+
.map_or(name, |(stem, _)| stem)
|
|
98
|
+
.trim_end_matches(' ');
|
|
99
|
+
let reserved = matches!(
|
|
100
|
+
stem.to_ascii_uppercase().as_bytes(),
|
|
101
|
+
b"CON"
|
|
102
|
+
| b"PRN"
|
|
103
|
+
| b"AUX"
|
|
104
|
+
| b"NUL"
|
|
105
|
+
| [b'C', b'O', b'M', b'1'..=b'9']
|
|
106
|
+
| [b'L', b'P', b'T', b'1'..=b'9']
|
|
107
|
+
);
|
|
108
|
+
!name.is_empty() && !name.ends_with(['.', ' ']) && !name.contains(invalid_char) && !reserved
|
|
52
109
|
}
|
|
53
110
|
|
|
54
111
|
/// A successful command run.
|
|
@@ -119,8 +176,8 @@ pub fn run_command(
|
|
|
119
176
|
let argv = build_argv(command, placeholders)?;
|
|
120
177
|
// `build_argv` guarantees a non-empty argv.
|
|
121
178
|
let mut cmd = Command::new(&argv[0]);
|
|
122
|
-
|
|
123
|
-
|
|
179
|
+
push_args(&mut cmd, &argv[1..]);
|
|
180
|
+
cmd.current_dir(cwd)
|
|
124
181
|
.stdout(Stdio::piped())
|
|
125
182
|
.stderr(Stdio::piped())
|
|
126
183
|
.stdin(if stdin_payload.is_some() {
|
|
@@ -193,6 +250,20 @@ pub fn run_command(
|
|
|
193
250
|
}
|
|
194
251
|
}
|
|
195
252
|
|
|
253
|
+
// One fn with cfg blocks rather than two cfg'd fns: cargo-mutants mutates
|
|
254
|
+
// the uncompiled twin too, and no test on a Linux gate can kill that mutant.
|
|
255
|
+
fn push_args(cmd: &mut Command, args: &[String]) {
|
|
256
|
+
#[cfg(windows)]
|
|
257
|
+
{
|
|
258
|
+
use std::os::windows::process::CommandExt;
|
|
259
|
+
for arg in args {
|
|
260
|
+
cmd.raw_arg(quote_windows_arg(arg));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
#[cfg(not(windows))]
|
|
264
|
+
cmd.args(args);
|
|
265
|
+
}
|
|
266
|
+
|
|
196
267
|
fn spawn_error(program: &str, source: std::io::Error, cwd: &Path) -> CommandError {
|
|
197
268
|
// A missing cwd fails the child's chdir with `NotFound` too.
|
|
198
269
|
if !searched_path(program, source.kind()) || !cwd.is_dir() {
|
|
@@ -244,6 +315,35 @@ pub(crate) fn build_argv(
|
|
|
244
315
|
Ok(argv)
|
|
245
316
|
}
|
|
246
317
|
|
|
318
|
+
/// Quote `arg` for a Windows command line by the MS C-runtime rules, always
|
|
319
|
+
/// wrapped in double quotes: an MSYS/Cygwin child globs, brace-expands and
|
|
320
|
+
/// unescapes any unquoted word, while an MSVCRT child parses the quoted form
|
|
321
|
+
/// back to `arg` exactly.
|
|
322
|
+
#[cfg_attr(not(windows), allow(dead_code))]
|
|
323
|
+
pub(crate) fn quote_windows_arg(arg: &str) -> String {
|
|
324
|
+
let mut out = String::with_capacity(arg.len() + 2);
|
|
325
|
+
out.push('"');
|
|
326
|
+
let mut backslashes = 0;
|
|
327
|
+
for ch in arg.chars() {
|
|
328
|
+
match ch {
|
|
329
|
+
'\\' => backslashes += 1,
|
|
330
|
+
'"' => {
|
|
331
|
+
out.extend(std::iter::repeat_n('\\', backslashes * 2 + 1));
|
|
332
|
+
out.push('"');
|
|
333
|
+
backslashes = 0;
|
|
334
|
+
}
|
|
335
|
+
_ => {
|
|
336
|
+
out.extend(std::iter::repeat_n('\\', backslashes));
|
|
337
|
+
out.push(ch);
|
|
338
|
+
backslashes = 0;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
out.extend(std::iter::repeat_n('\\', backslashes * 2));
|
|
343
|
+
out.push('"');
|
|
344
|
+
out
|
|
345
|
+
}
|
|
346
|
+
|
|
247
347
|
/// Replace every `{name}` in `token` with its placeholder value in a single
|
|
248
348
|
/// left-to-right pass. Injected values are never re-scanned, so an untrusted
|
|
249
349
|
/// value containing `{…}` is inert. Unknown `{…}` sequences are left literal.
|
|
@@ -315,6 +415,117 @@ mod tests {
|
|
|
315
415
|
build_argv(command, placeholders).expect("valid command")
|
|
316
416
|
}
|
|
317
417
|
|
|
418
|
+
fn unchanged(path: &str) {
|
|
419
|
+
assert_eq!(non_verbatim(path), path);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
#[test]
|
|
423
|
+
fn non_verbatim_strips_a_verbatim_drive_path() {
|
|
424
|
+
assert_eq!(
|
|
425
|
+
non_verbatim(r"\\?\C:\Users\runner\in_cwd.txt"),
|
|
426
|
+
r"C:\Users\runner\in_cwd.txt"
|
|
427
|
+
);
|
|
428
|
+
assert_eq!(non_verbatim(r"\\?\d:\x"), r"d:\x");
|
|
429
|
+
assert_eq!(non_verbatim(r"\\?\C:\my file.txt"), r"C:\my file.txt");
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
#[test]
|
|
433
|
+
fn non_verbatim_strips_a_verbatim_drive_root() {
|
|
434
|
+
assert_eq!(non_verbatim(r"\\?\C:\"), r"C:\");
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
#[test]
|
|
438
|
+
fn non_verbatim_rewrites_a_verbatim_unc_path() {
|
|
439
|
+
assert_eq!(
|
|
440
|
+
non_verbatim(r"\\?\UNC\server\share\dir\f.txt"),
|
|
441
|
+
r"\\server\share\dir\f.txt"
|
|
442
|
+
);
|
|
443
|
+
assert_eq!(non_verbatim(r"\\?\UNC\server\share"), r"\\server\share");
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
#[test]
|
|
447
|
+
fn non_verbatim_leaves_plain_paths_unchanged() {
|
|
448
|
+
unchanged(r"C:\Users\runner\f.txt");
|
|
449
|
+
unchanged(r"\\server\share\f.txt");
|
|
450
|
+
unchanged("/tmp/root/f.txt");
|
|
451
|
+
unchanged("relative/f.txt");
|
|
452
|
+
unchanged("");
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
#[test]
|
|
456
|
+
fn non_verbatim_leaves_verbatim_forms_without_a_drive_or_unc_unchanged() {
|
|
457
|
+
unchanged(r"\\?\GLOBALROOT\Device\HarddiskVolume1\f.txt");
|
|
458
|
+
unchanged(r"\\?\Volume{0b1c2d3e-0000-0000-0000-100000000000}\f.txt");
|
|
459
|
+
unchanged(r"\\?\C:");
|
|
460
|
+
unchanged(r"\\?\C:x");
|
|
461
|
+
unchanged(r"\\?\1:\x");
|
|
462
|
+
unchanged(r"\\?\");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
#[test]
|
|
466
|
+
fn non_verbatim_leaves_an_incomplete_unc_unchanged() {
|
|
467
|
+
unchanged(r"\\?\UNC\");
|
|
468
|
+
unchanged(r"\\?\UNC\server");
|
|
469
|
+
unchanged(r"\\?\UNC\server\");
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
#[test]
|
|
473
|
+
fn non_verbatim_leaves_components_win32_would_reinterpret_unchanged() {
|
|
474
|
+
unchanged(r"\\?\C:\a\..\b");
|
|
475
|
+
unchanged(r"\\?\C:\a\.\b");
|
|
476
|
+
unchanged(r"\\?\C:\a\\b");
|
|
477
|
+
unchanged(r"\\?\C:\a\");
|
|
478
|
+
unchanged(r"\\?\C:\trailing.");
|
|
479
|
+
unchanged(r"\\?\C:\trailing ");
|
|
480
|
+
unchanged(r"\\?\C:\a/b");
|
|
481
|
+
unchanged(r"\\?\C:\a?b");
|
|
482
|
+
unchanged(r"\\?\C:\a*b");
|
|
483
|
+
unchanged(r"\\?\C:\a:b");
|
|
484
|
+
unchanged(r#"\\?\C:\a"b"#);
|
|
485
|
+
unchanged(r"\\?\C:\a<b");
|
|
486
|
+
unchanged(r"\\?\C:\a>b");
|
|
487
|
+
unchanged(r"\\?\C:\a|b");
|
|
488
|
+
unchanged("\\\\?\\C:\\a\u{1}b");
|
|
489
|
+
unchanged(r"\\?\UNC\server\share\..\x");
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
#[test]
|
|
493
|
+
fn non_verbatim_leaves_reserved_device_names_unchanged() {
|
|
494
|
+
for name in [
|
|
495
|
+
"CON", "con", "PRN", "AUX", "NUL", "nul.txt", "NUL .txt", "COM1", "COM9", "LPT1",
|
|
496
|
+
"lpt9.log",
|
|
497
|
+
] {
|
|
498
|
+
unchanged(&format!(r"\\?\C:\dir\{name}"));
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
#[test]
|
|
503
|
+
fn non_verbatim_strips_names_that_only_resemble_device_names() {
|
|
504
|
+
for name in [
|
|
505
|
+
"CONSOLE", "NULL.txt", "COM0", "COM10", "LPT", "xCON", "AUXa",
|
|
506
|
+
] {
|
|
507
|
+
assert_eq!(
|
|
508
|
+
non_verbatim(&format!(r"\\?\C:\dir\{name}")),
|
|
509
|
+
format!(r"C:\dir\{name}")
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#[test]
|
|
515
|
+
fn non_verbatim_strips_up_to_max_path_and_no_further() {
|
|
516
|
+
let fits = format!(r"C:\{}", "a".repeat(256));
|
|
517
|
+
assert_eq!(fits.encode_utf16().count(), 259);
|
|
518
|
+
assert_eq!(non_verbatim(&format!(r"\\?\{fits}")), fits);
|
|
519
|
+
unchanged(&format!(r"\\?\C:\{}", "a".repeat(257)));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#[test]
|
|
523
|
+
fn path_placeholder_carries_the_non_verbatim_value() {
|
|
524
|
+
let placeholder = Placeholder::path("path", r"\\?\C:\a\f.txt");
|
|
525
|
+
assert_eq!(placeholder.name, "path");
|
|
526
|
+
assert_eq!(placeholder.value, r"C:\a\f.txt");
|
|
527
|
+
}
|
|
528
|
+
|
|
318
529
|
#[test]
|
|
319
530
|
fn splits_on_whitespace_without_placeholders() {
|
|
320
531
|
assert_eq!(argv("echo hello world", &[]), ["echo", "hello", "world"]);
|
|
@@ -402,6 +613,47 @@ mod tests {
|
|
|
402
613
|
assert_eq!(argv("run", &[Placeholder::new("path", "/tmp/x")]), ["run"]);
|
|
403
614
|
}
|
|
404
615
|
|
|
616
|
+
#[test]
|
|
617
|
+
fn windows_quoting_wraps_a_plain_arg_in_quotes() {
|
|
618
|
+
assert_eq!(quote_windows_arg("hello"), r#""hello""#);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
#[test]
|
|
622
|
+
fn windows_quoting_keeps_an_empty_arg_as_an_empty_quoted_word() {
|
|
623
|
+
assert_eq!(quote_windows_arg(""), r#""""#);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
#[test]
|
|
627
|
+
fn windows_quoting_quotes_glob_and_brace_characters() {
|
|
628
|
+
assert_eq!(quote_windows_arg("[{}]"), r#""[{}]""#);
|
|
629
|
+
assert_eq!(quote_windows_arg("a?b*c"), r#""a?b*c""#);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
#[test]
|
|
633
|
+
fn windows_quoting_leaves_backslashes_not_before_a_quote_alone() {
|
|
634
|
+
assert_eq!(
|
|
635
|
+
quote_windows_arg(r"\\?\C:\Users\x.txt"),
|
|
636
|
+
r#""\\?\C:\Users\x.txt""#
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
#[test]
|
|
641
|
+
fn windows_quoting_doubles_trailing_backslashes_before_the_closing_quote() {
|
|
642
|
+
assert_eq!(quote_windows_arg(r"C:\dir\"), r#""C:\dir\\""#);
|
|
643
|
+
assert_eq!(quote_windows_arg(r"a\\"), r#""a\\\\""#);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
#[test]
|
|
647
|
+
fn windows_quoting_escapes_embedded_quotes() {
|
|
648
|
+
assert_eq!(quote_windows_arg(r#"[{"n":1}]"#), r#""[{\"n\":1}]""#);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
#[test]
|
|
652
|
+
fn windows_quoting_doubles_backslashes_before_an_embedded_quote() {
|
|
653
|
+
assert_eq!(quote_windows_arg(r#"a\"b"#), r#""a\\\"b""#);
|
|
654
|
+
assert_eq!(quote_windows_arg(r#"a\\"b"#), r#""a\\\\\"b""#);
|
|
655
|
+
}
|
|
656
|
+
|
|
405
657
|
#[test]
|
|
406
658
|
fn extract_payload_takes_the_last_non_empty_line() {
|
|
407
659
|
assert_eq!(
|
|
@@ -512,7 +512,11 @@ mod tests {
|
|
|
512
512
|
);
|
|
513
513
|
assert_eq!(
|
|
514
514
|
err.to_string(),
|
|
515
|
-
|
|
515
|
+
format!(
|
|
516
|
+
"multiple loadable extension files found in package 'vec': {}, {}; disambiguate with a literal path",
|
|
517
|
+
dir.join("a.so").display(),
|
|
518
|
+
dir.join("z.so").display()
|
|
519
|
+
)
|
|
516
520
|
);
|
|
517
521
|
}
|
|
518
522
|
}
|
|
@@ -1938,8 +1938,8 @@ fn run_on_file(
|
|
|
1938
1938
|
root: &Path,
|
|
1939
1939
|
) -> std::result::Result<Vec<Row>, BoxError> {
|
|
1940
1940
|
let placeholders = [
|
|
1941
|
-
Placeholder::
|
|
1942
|
-
Placeholder::
|
|
1941
|
+
Placeholder::path("path", abs_path),
|
|
1942
|
+
Placeholder::path("root", &root.to_string_lossy()),
|
|
1943
1943
|
];
|
|
1944
1944
|
|
|
1945
1945
|
// Errors travel to the caller rather than being logged and flattened to an
|
|
@@ -2936,7 +2936,12 @@ mod internal_tests {
|
|
|
2936
2936
|
/// so `notify` never sees `.`.
|
|
2937
2937
|
#[test]
|
|
2938
2938
|
fn relative_root_canonicalizes_watch_root_only() {
|
|
2939
|
-
let
|
|
2939
|
+
let canonical = if cfg!(windows) {
|
|
2940
|
+
r"C:\ws\canonical"
|
|
2941
|
+
} else {
|
|
2942
|
+
"/ws/canonical"
|
|
2943
|
+
};
|
|
2944
|
+
let fake = FakeFs::default().with_canonical_root(".", canonical);
|
|
2940
2945
|
let db = DirSQL::with_ignore_and_fs(
|
|
2941
2946
|
".",
|
|
2942
2947
|
vec![Table::new(
|
|
@@ -2956,7 +2961,7 @@ mod internal_tests {
|
|
|
2956
2961
|
"watch_root must be absolute, got {:?}",
|
|
2957
2962
|
db.inner.watch_root
|
|
2958
2963
|
);
|
|
2959
|
-
assert_eq!(db.inner.watch_root, PathBuf::from(
|
|
2964
|
+
assert_eq!(db.inner.watch_root, PathBuf::from(canonical));
|
|
2960
2965
|
}
|
|
2961
2966
|
|
|
2962
2967
|
/// With an absolute root, `process_file_event` strips the `watch_root`
|
|
@@ -4376,6 +4381,22 @@ mod internal_tests {
|
|
|
4376
4381
|
);
|
|
4377
4382
|
}
|
|
4378
4383
|
|
|
4384
|
+
#[test]
|
|
4385
|
+
fn run_on_file_hands_the_hook_non_verbatim_path_and_root() {
|
|
4386
|
+
let dir = TempDir::new().unwrap();
|
|
4387
|
+
run_on_file(
|
|
4388
|
+
r#"sh -c 'printf "%s|%s" "$1" "$2" > seen; echo "[]"' sh {path} {root}"#,
|
|
4389
|
+
r"\\?\C:\r\f.txt",
|
|
4390
|
+
dir.path(),
|
|
4391
|
+
Path::new(r"\\?\D:\r"),
|
|
4392
|
+
)
|
|
4393
|
+
.expect("a well-formed payload parses");
|
|
4394
|
+
assert_eq!(
|
|
4395
|
+
std::fs::read_to_string(dir.path().join("seen")).unwrap(),
|
|
4396
|
+
r"C:\r\f.txt|D:\r"
|
|
4397
|
+
);
|
|
4398
|
+
}
|
|
4399
|
+
|
|
4379
4400
|
/// A command that cannot be spawned is an error the caller records, not an
|
|
4380
4401
|
/// empty row set: a skip and a file that legitimately produced no rows must
|
|
4381
4402
|
/// stay distinguishable.
|
|
@@ -292,8 +292,8 @@ fn no_rows_message(pattern: &str) -> String {
|
|
|
292
292
|
fn run_parser(command: &str, root: &Path, rel_path: &Path) -> std::result::Result<String, String> {
|
|
293
293
|
let abs_path = root.join(rel_path);
|
|
294
294
|
let placeholders = [
|
|
295
|
-
Placeholder::
|
|
296
|
-
Placeholder::
|
|
295
|
+
Placeholder::path("path", &abs_path.to_string_lossy()),
|
|
296
|
+
Placeholder::path("root", &root.to_string_lossy()),
|
|
297
297
|
];
|
|
298
298
|
|
|
299
299
|
run_command(command, &placeholders, root, None)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md
RENAMED
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md
RENAMED
|
File without changes
|
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md
RENAMED
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-07-29-restore-python-310.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md
RENAMED
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md
RENAMED
|
File without changes
|
{dirsql-0.4.59 → dirsql-0.4.60}/packages/python/changelog.d/2026-08-20-declared-table-name.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|