dirsql 0.4.57__tar.gz → 0.4.58__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.57 → dirsql-0.4.58}/Cargo.lock +9 -2
- {dirsql-0.4.57 → dirsql-0.4.58}/PKG-INFO +1 -1
- {dirsql-0.4.57/packages/python → dirsql-0.4.58}/docs/reference/path-tables.md +6 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/Cargo.toml +1 -1
- {dirsql-0.4.57 → dirsql-0.4.58/packages/python}/docs/reference/path-tables.md +6 -0
- dirsql-0.4.58/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +7 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/Cargo.toml +2 -1
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/path-tables.md +6 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/path_table.rs +316 -35
- {dirsql-0.4.57 → dirsql-0.4.58}/Cargo.toml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/README.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/_async.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/main.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/plan_entry_path.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/py.typed +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/read_config.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/resolve_configs_extension_specs.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/dirsql/resolve_package.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/AGENTS.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/explanation.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/getting-started.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/embed.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/persist.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/query-json.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/index.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/package.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/plugins.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/cli.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/hooks.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/http-api.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/README.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/conftest.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/query-json.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/plugins.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/src/lib.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/testing-conventions.toml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/e2e/speed_of_light.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/README.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/query-json.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/search-indexes.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/howto/write-a-plugin.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/plugins.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/repl.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/run.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/cli/table.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/command.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/config.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/extension_resolution.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/functions.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/launcher.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/parsed_cache.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/progress.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/row_event_flat.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/sql_literal.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/vtab_scaffold.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.4.57 → dirsql-0.4.58}/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.58"
|
|
556
556
|
dependencies = [
|
|
557
557
|
"assert_cmd",
|
|
558
558
|
"axum",
|
|
@@ -584,6 +584,7 @@ dependencies = [
|
|
|
584
584
|
"tokio",
|
|
585
585
|
"tokio-stream",
|
|
586
586
|
"toml",
|
|
587
|
+
"typed-path",
|
|
587
588
|
"walkdir",
|
|
588
589
|
]
|
|
589
590
|
|
|
@@ -600,7 +601,7 @@ dependencies = [
|
|
|
600
601
|
|
|
601
602
|
[[package]]
|
|
602
603
|
name = "dirsql-py-ext"
|
|
603
|
-
version = "0.4.
|
|
604
|
+
version = "0.4.58"
|
|
604
605
|
dependencies = [
|
|
605
606
|
"dirsql",
|
|
606
607
|
"pyo3",
|
|
@@ -2915,6 +2916,12 @@ version = "0.2.5"
|
|
|
2915
2916
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2916
2917
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|
2917
2918
|
|
|
2919
|
+
[[package]]
|
|
2920
|
+
name = "typed-path"
|
|
2921
|
+
version = "0.12.3"
|
|
2922
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2923
|
+
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
|
|
2924
|
+
|
|
2918
2925
|
[[package]]
|
|
2919
2926
|
name = "unicase"
|
|
2920
2927
|
version = "2.9.0"
|
|
@@ -96,6 +96,12 @@ SELECT path FROM '/var/log/*.log';
|
|
|
96
96
|
-- /var/log/syslog
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
On Windows, the absolute forms also include a drive letter
|
|
100
|
+
(`'C:\logs\*.log'` or `'C:/logs/*.log'`), a UNC share
|
|
101
|
+
(`'\\server\share\*.md'`) and `'~\notes'`. `\` and `/` both separate there,
|
|
102
|
+
and the `path` these report uses `/` throughout (`C:/logs/app.log`), matching
|
|
103
|
+
the `/`-separated relative paths.
|
|
104
|
+
|
|
99
105
|
On a system with no home directory, a `~/` path-table reports that it cannot
|
|
100
106
|
resolve rather than guessing.
|
|
101
107
|
|
|
@@ -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.58"
|
|
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
|
|
@@ -96,6 +96,12 @@ SELECT path FROM '/var/log/*.log';
|
|
|
96
96
|
-- /var/log/syslog
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
On Windows, the absolute forms also include a drive letter
|
|
100
|
+
(`'C:\logs\*.log'` or `'C:/logs/*.log'`), a UNC share
|
|
101
|
+
(`'\\server\share\*.md'`) and `'~\notes'`. `\` and `/` both separate there,
|
|
102
|
+
and the `path` these report uses `/` throughout (`C:/logs/app.log`), matching
|
|
103
|
+
the `/`-separated relative paths.
|
|
104
|
+
|
|
99
105
|
On a system with no home directory, a `~/` path-table reports that it cannot
|
|
100
106
|
resolve rather than guessing.
|
|
101
107
|
|
|
@@ -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.58"
|
|
10
10
|
edition.workspace = true
|
|
11
11
|
# Literal `license` (not `license.workspace = true`) because
|
|
12
12
|
# putitoutthere's preflight check reads `[package].license` directly
|
|
@@ -86,6 +86,7 @@ thiserror.workspace = true
|
|
|
86
86
|
tokio.workspace = true
|
|
87
87
|
tokio-stream = { version = "0.1", features = ["sync"], optional = true }
|
|
88
88
|
toml = "0.8"
|
|
89
|
+
typed-path = "0.12"
|
|
89
90
|
walkdir = "2"
|
|
90
91
|
|
|
91
92
|
[lints.rust]
|
|
@@ -96,6 +96,12 @@ SELECT path FROM '/var/log/*.log';
|
|
|
96
96
|
-- /var/log/syslog
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
On Windows, the absolute forms also include a drive letter
|
|
100
|
+
(`'C:\logs\*.log'` or `'C:/logs/*.log'`), a UNC share
|
|
101
|
+
(`'\\server\share\*.md'`) and `'~\notes'`. `\` and `/` both separate there,
|
|
102
|
+
and the `path` these report uses `/` throughout (`C:/logs/app.log`), matching
|
|
103
|
+
the `/`-separated relative paths.
|
|
104
|
+
|
|
99
105
|
On a system with no home directory, a `~/` path-table reports that it cannot
|
|
100
106
|
resolve rather than guessing.
|
|
101
107
|
|
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
//!
|
|
5
5
|
//! Every decision here is a pure function of the written string plus one
|
|
6
6
|
//! filesystem question (*is this a directory?*), which is injected so the
|
|
7
|
-
//! rules can be tested without a filesystem.
|
|
7
|
+
//! rules can be tested without a filesystem. The path syntax is a type
|
|
8
|
+
//! parameter, so the Windows rules are testable on any host.
|
|
8
9
|
|
|
9
|
-
use std::path::{
|
|
10
|
+
use std::path::{Path, PathBuf};
|
|
11
|
+
|
|
12
|
+
use typed_path::{
|
|
13
|
+
Utf8Component, Utf8Encoding, Utf8NativeEncoding, Utf8Path, Utf8PathBuf, Utf8UnixEncoding,
|
|
14
|
+
Utf8WindowsComponent, Utf8WindowsEncoding, Utf8WindowsPath,
|
|
15
|
+
};
|
|
10
16
|
|
|
11
17
|
/// Directories a path-table scan skips, at any depth. They are skipped only
|
|
12
18
|
/// *beneath* the literal part of the path you write, so naming one explicitly
|
|
@@ -43,6 +49,50 @@ pub enum Resolution {
|
|
|
43
49
|
NotAPath,
|
|
44
50
|
}
|
|
45
51
|
|
|
52
|
+
/// The per-platform rules for which written names are absolute and how a
|
|
53
|
+
/// resolved scan root is reported.
|
|
54
|
+
trait Syntax: Utf8Encoding + Sized {
|
|
55
|
+
const HOME_PREFIXES: &'static [&'static str];
|
|
56
|
+
|
|
57
|
+
fn is_rooted(name: &str) -> bool;
|
|
58
|
+
|
|
59
|
+
fn reported(path: &Utf8Path<Self>) -> String;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
impl Syntax for Utf8UnixEncoding {
|
|
63
|
+
const HOME_PREFIXES: &'static [&'static str] = &["~/"];
|
|
64
|
+
|
|
65
|
+
fn is_rooted(name: &str) -> bool {
|
|
66
|
+
name.starts_with('/')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fn reported(path: &Utf8Path<Self>) -> String {
|
|
70
|
+
path.as_str().to_string()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl Syntax for Utf8WindowsEncoding {
|
|
75
|
+
const HOME_PREFIXES: &'static [&'static str] = &["~/", "~\\"];
|
|
76
|
+
|
|
77
|
+
fn is_rooted(name: &str) -> bool {
|
|
78
|
+
Utf8WindowsPath::new(name).has_root()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Reported with `/`, matching the index-root-relative paths. A verbatim
|
|
82
|
+
/// (`\\?\`) path is the exception: there `/` is not a separator.
|
|
83
|
+
fn reported(path: &Utf8Path<Self>) -> String {
|
|
84
|
+
let verbatim = matches!(
|
|
85
|
+
path.components().next(),
|
|
86
|
+
Some(Utf8WindowsComponent::Prefix(prefix)) if prefix.kind().is_verbatim()
|
|
87
|
+
);
|
|
88
|
+
if verbatim {
|
|
89
|
+
path.as_str().to_string()
|
|
90
|
+
} else {
|
|
91
|
+
path.as_str().replace('\\', "/")
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
46
96
|
/// Whether `name` contains a character that makes it a glob rather than a
|
|
47
97
|
/// literal path.
|
|
48
98
|
fn has_glob_metacharacter(name: &str) -> bool {
|
|
@@ -58,6 +108,15 @@ pub fn resolve(
|
|
|
58
108
|
index_root: &Path,
|
|
59
109
|
home: Option<&Path>,
|
|
60
110
|
is_dir: &dyn Fn(&Path) -> bool,
|
|
111
|
+
) -> Resolution {
|
|
112
|
+
resolve_as::<Utf8NativeEncoding>(name, index_root, home, is_dir)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fn resolve_as<S: Syntax>(
|
|
116
|
+
name: &str,
|
|
117
|
+
index_root: &Path,
|
|
118
|
+
home: Option<&Path>,
|
|
119
|
+
is_dir: &dyn Fn(&Path) -> bool,
|
|
61
120
|
) -> Resolution {
|
|
62
121
|
if let Some(rest) = name.strip_prefix("./") {
|
|
63
122
|
return Resolution::Table(PathTable {
|
|
@@ -67,7 +126,7 @@ pub fn resolve(
|
|
|
67
126
|
});
|
|
68
127
|
}
|
|
69
128
|
|
|
70
|
-
match absolute_target(name, index_root, home) {
|
|
129
|
+
match absolute_target::<S>(name, index_root, home) {
|
|
71
130
|
Some(Some(target)) => Resolution::Table(split_absolute(&target, is_dir)),
|
|
72
131
|
Some(None) => Resolution::NoHome,
|
|
73
132
|
None if has_glob_metacharacter(name) => Resolution::Hint,
|
|
@@ -91,19 +150,27 @@ fn relative_glob(rest: &str, is_dir: &dyn Fn(&Path) -> bool) -> String {
|
|
|
91
150
|
trimmed.to_string()
|
|
92
151
|
}
|
|
93
152
|
|
|
153
|
+
fn typed<S: Syntax>(path: &Path) -> Utf8PathBuf<S> {
|
|
154
|
+
Utf8PathBuf::from(path.to_string_lossy().into_owned())
|
|
155
|
+
}
|
|
156
|
+
|
|
94
157
|
/// The absolute path a non-`./` path-table names, with `.` and `..` folded out.
|
|
95
158
|
///
|
|
96
159
|
/// `None` means the name is not a path at all. `Some(None)` means it is a `~/`
|
|
97
160
|
/// path but no home directory could be found.
|
|
98
|
-
fn absolute_target
|
|
99
|
-
|
|
100
|
-
|
|
161
|
+
fn absolute_target<S: Syntax>(
|
|
162
|
+
name: &str,
|
|
163
|
+
index_root: &Path,
|
|
164
|
+
home: Option<&Path>,
|
|
165
|
+
) -> Option<Option<Utf8PathBuf<S>>> {
|
|
166
|
+
if let Some(rest) = S::HOME_PREFIXES.iter().find_map(|p| name.strip_prefix(p)) {
|
|
167
|
+
return Some(home.map(|h| normalize(&typed::<S>(h).join(rest))));
|
|
101
168
|
}
|
|
102
169
|
if name.starts_with("../") {
|
|
103
|
-
return Some(Some(normalize(&index_root.join(name))));
|
|
170
|
+
return Some(Some(normalize(&typed::<S>(index_root).join(name))));
|
|
104
171
|
}
|
|
105
|
-
if name
|
|
106
|
-
return Some(Some(normalize(
|
|
172
|
+
if S::is_rooted(name) {
|
|
173
|
+
return Some(Some(normalize(Utf8Path::new(name))));
|
|
107
174
|
}
|
|
108
175
|
None
|
|
109
176
|
}
|
|
@@ -111,21 +178,37 @@ fn absolute_target(name: &str, index_root: &Path, home: Option<&Path>) -> Option
|
|
|
111
178
|
/// Fold `.` and `..` out of `path` lexically. Purely textual: a `..` is not
|
|
112
179
|
/// resolved through a symlink, which keeps the answer a function of the string
|
|
113
180
|
/// the user wrote.
|
|
114
|
-
fn normalize(path: &
|
|
115
|
-
let mut
|
|
181
|
+
fn normalize<S: Syntax>(path: &Utf8Path<S>) -> Utf8PathBuf<S> {
|
|
182
|
+
let mut kept: Vec<&str> = Vec::new();
|
|
183
|
+
let mut normal = 0;
|
|
184
|
+
let mut rooted = false;
|
|
116
185
|
for component in path.components() {
|
|
117
|
-
|
|
118
|
-
|
|
186
|
+
if component.is_current() {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if component.is_parent() {
|
|
119
190
|
// A `..` that cannot pop is kept on a relative path (it still
|
|
120
191
|
// means something) but dropped at the filesystem root, which has
|
|
121
192
|
// no parent to climb to.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
193
|
+
if normal > 0 {
|
|
194
|
+
kept.pop();
|
|
195
|
+
normal -= 1;
|
|
196
|
+
} else if !rooted {
|
|
197
|
+
kept.push(component.as_str());
|
|
126
198
|
}
|
|
127
|
-
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if component.is_normal() {
|
|
202
|
+
normal += 1;
|
|
203
|
+
} else if component.is_root() {
|
|
204
|
+
rooted = true;
|
|
128
205
|
}
|
|
206
|
+
kept.push(component.as_str());
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let mut out = Utf8PathBuf::new();
|
|
210
|
+
for component in kept {
|
|
211
|
+
out.push(component);
|
|
129
212
|
}
|
|
130
213
|
out
|
|
131
214
|
}
|
|
@@ -133,43 +216,44 @@ fn normalize(path: &Path) -> PathBuf {
|
|
|
133
216
|
/// Split an absolute path-table target into the directory to walk and the glob
|
|
134
217
|
/// to match beneath it. A wholly literal target is a directory (scan it
|
|
135
218
|
/// recursively) or a single file (match exactly that name).
|
|
136
|
-
fn split_absolute(target: &
|
|
219
|
+
fn split_absolute<S: Syntax>(target: &Utf8Path<S>, is_dir: &dyn Fn(&Path) -> bool) -> PathTable {
|
|
137
220
|
let (literal, rest) = split_at_first_glob(target);
|
|
138
221
|
|
|
139
222
|
if !rest.is_empty() {
|
|
140
|
-
return table_at(literal, rest);
|
|
223
|
+
return table_at(&literal, rest);
|
|
141
224
|
}
|
|
142
|
-
if is_dir(
|
|
143
|
-
return table_at(literal, RECURSIVE_GLOB.to_string());
|
|
225
|
+
if is_dir(Path::new(literal.as_str())) {
|
|
226
|
+
return table_at(&literal, RECURSIVE_GLOB.to_string());
|
|
144
227
|
}
|
|
145
228
|
|
|
146
229
|
let name = literal
|
|
147
230
|
.file_name()
|
|
148
|
-
.map(
|
|
231
|
+
.map(str::to_string)
|
|
149
232
|
.unwrap_or_else(|| RECURSIVE_GLOB.to_string());
|
|
150
|
-
let parent = literal.parent().unwrap_or(&literal)
|
|
233
|
+
let parent = literal.parent().unwrap_or(&literal);
|
|
151
234
|
table_at(parent, name)
|
|
152
235
|
}
|
|
153
236
|
|
|
154
237
|
/// A path-table rooted at `root`, reporting absolute paths.
|
|
155
|
-
fn table_at(root:
|
|
238
|
+
fn table_at<S: Syntax>(root: &Utf8Path<S>, glob: String) -> PathTable {
|
|
156
239
|
PathTable {
|
|
157
|
-
path_prefix: root
|
|
158
|
-
root,
|
|
240
|
+
path_prefix: S::reported(root),
|
|
241
|
+
root: PathBuf::from(root.as_str()),
|
|
159
242
|
glob,
|
|
160
243
|
}
|
|
161
244
|
}
|
|
162
245
|
|
|
163
246
|
/// Split `target` at its first glob-bearing component: the literal directory
|
|
164
247
|
/// chain ahead of it, and the rest as a `/`-joined glob.
|
|
165
|
-
fn split_at_first_glob(target: &
|
|
166
|
-
let mut literal =
|
|
167
|
-
let mut rest: Vec
|
|
248
|
+
fn split_at_first_glob<S: Syntax>(target: &Utf8Path<S>) -> (Utf8PathBuf<S>, String) {
|
|
249
|
+
let mut literal = Utf8PathBuf::new();
|
|
250
|
+
let mut rest: Vec<&str> = Vec::new();
|
|
168
251
|
|
|
169
252
|
for component in target.components() {
|
|
170
|
-
let text = component.
|
|
171
|
-
|
|
172
|
-
|
|
253
|
+
let text = component.as_str();
|
|
254
|
+
let is_glob = component.is_normal() && has_glob_metacharacter(text);
|
|
255
|
+
if rest.is_empty() && !is_glob {
|
|
256
|
+
literal.push(text);
|
|
173
257
|
} else {
|
|
174
258
|
rest.push(text);
|
|
175
259
|
}
|
|
@@ -388,12 +472,23 @@ mod tests {
|
|
|
388
472
|
|
|
389
473
|
#[test]
|
|
390
474
|
fn normalize_drops_current_directory_components() {
|
|
391
|
-
assert_eq!(
|
|
475
|
+
assert_eq!(unix_normalize("/a/./b"), "/a/b");
|
|
392
476
|
}
|
|
393
477
|
|
|
394
478
|
#[test]
|
|
395
479
|
fn normalize_keeps_a_leading_parent_it_cannot_pop() {
|
|
396
|
-
assert_eq!(
|
|
480
|
+
assert_eq!(unix_normalize("../a"), "../a");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
#[test]
|
|
484
|
+
fn normalize_does_not_pop_a_parent_it_kept() {
|
|
485
|
+
assert_eq!(unix_normalize("../../a"), "../../a");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
fn unix_normalize(path: &str) -> String {
|
|
489
|
+
normalize(Utf8Path::<Utf8UnixEncoding>::new(path))
|
|
490
|
+
.as_str()
|
|
491
|
+
.to_string()
|
|
397
492
|
}
|
|
398
493
|
|
|
399
494
|
#[test]
|
|
@@ -413,4 +508,190 @@ mod tests {
|
|
|
413
508
|
fn ignore_base_is_the_whole_of_a_literal_glob() {
|
|
414
509
|
assert_eq!(ignore_base("docs/a.md"), PathBuf::from("docs/a.md"));
|
|
415
510
|
}
|
|
511
|
+
|
|
512
|
+
mod windows {
|
|
513
|
+
use super::*;
|
|
514
|
+
|
|
515
|
+
const ROOT: &str = r"C:\index";
|
|
516
|
+
|
|
517
|
+
fn resolve_with(name: &str, is_dir: &dyn Fn(&Path) -> bool) -> Resolution {
|
|
518
|
+
resolve_as::<Utf8WindowsEncoding>(
|
|
519
|
+
name,
|
|
520
|
+
Path::new(ROOT),
|
|
521
|
+
Some(Path::new(r"C:\Users\u")),
|
|
522
|
+
is_dir,
|
|
523
|
+
)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
fn table(name: &str, is_dir: &dyn Fn(&Path) -> bool) -> PathTable {
|
|
527
|
+
match resolve_with(name, is_dir) {
|
|
528
|
+
Resolution::Table(t) => t,
|
|
529
|
+
other => panic!("expected a path-table, got {other:?}"),
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
#[test]
|
|
534
|
+
fn a_drive_letter_glob_roots_at_its_literal_prefix() {
|
|
535
|
+
let t = table(r"C:\var\log\*.log", ¬hing_is_a_dir);
|
|
536
|
+
assert_eq!(t.root, Path::new(r"C:\var\log"));
|
|
537
|
+
assert_eq!(t.glob, "*.log");
|
|
538
|
+
assert_eq!(t.path_prefix, "C:/var/log");
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
#[test]
|
|
542
|
+
fn a_drive_letter_path_may_use_forward_slashes() {
|
|
543
|
+
let t = table("C:/var/log/*.log", ¬hing_is_a_dir);
|
|
544
|
+
assert_eq!(t.root, Path::new(r"C:\var\log"));
|
|
545
|
+
assert_eq!(t.path_prefix, "C:/var/log");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
#[test]
|
|
549
|
+
fn a_mixed_separator_path_splits_on_both() {
|
|
550
|
+
let t = table(r"C:\Users\u\Temp/docs/*.md", ¬hing_is_a_dir);
|
|
551
|
+
assert_eq!(t.root, Path::new(r"C:\Users\u\Temp\docs"));
|
|
552
|
+
assert_eq!(t.glob, "*.md");
|
|
553
|
+
assert_eq!(t.path_prefix, "C:/Users/u/Temp/docs");
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
#[test]
|
|
557
|
+
fn a_drive_letter_directory_expands_recursively() {
|
|
558
|
+
let t = table(r"C:\var\log", &everything_is_a_dir);
|
|
559
|
+
assert_eq!(t.root, Path::new(r"C:\var\log"));
|
|
560
|
+
assert_eq!(t.glob, "**/*");
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
#[test]
|
|
564
|
+
fn a_drive_letter_single_file_roots_at_its_parent() {
|
|
565
|
+
let t = table(r"C:\var\log\syslog", ¬hing_is_a_dir);
|
|
566
|
+
assert_eq!(t.root, Path::new(r"C:\var\log"));
|
|
567
|
+
assert_eq!(t.glob, "syslog");
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
#[test]
|
|
571
|
+
fn a_drive_root_scans_everything() {
|
|
572
|
+
let t = table(r"C:\", &everything_is_a_dir);
|
|
573
|
+
assert_eq!(t.root, Path::new(r"C:\"));
|
|
574
|
+
assert_eq!(t.glob, "**/*");
|
|
575
|
+
assert_eq!(t.path_prefix, "C:/");
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
#[test]
|
|
579
|
+
fn a_drive_relative_name_is_not_a_path() {
|
|
580
|
+
assert_eq!(
|
|
581
|
+
resolve_with("C:notes", ¬hing_is_a_dir),
|
|
582
|
+
Resolution::NotAPath
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
#[test]
|
|
587
|
+
fn a_rooted_path_without_a_drive_is_still_absolute() {
|
|
588
|
+
let t = table("/var/log/*.log", ¬hing_is_a_dir);
|
|
589
|
+
assert_eq!(t.root, Path::new(r"\var\log"));
|
|
590
|
+
assert_eq!(t.path_prefix, "/var/log");
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
#[test]
|
|
594
|
+
fn a_unc_path_roots_at_its_share() {
|
|
595
|
+
let t = table(r"\\server\share\docs\*.md", ¬hing_is_a_dir);
|
|
596
|
+
assert_eq!(t.root, Path::new(r"\\server\share\docs"));
|
|
597
|
+
assert_eq!(t.glob, "*.md");
|
|
598
|
+
assert_eq!(t.path_prefix, "//server/share/docs");
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
#[test]
|
|
602
|
+
fn a_verbatim_path_keeps_its_backslashes() {
|
|
603
|
+
let t = table(r"\\?\C:\var\log\*.log", ¬hing_is_a_dir);
|
|
604
|
+
assert_eq!(t.path_prefix, r"\\?\C:\var\log");
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
#[test]
|
|
608
|
+
fn a_parent_relative_path_resolves_against_the_index_root() {
|
|
609
|
+
let t = resolve_as::<Utf8WindowsEncoding>(
|
|
610
|
+
"../../a/*.md",
|
|
611
|
+
Path::new(r"C:\x\y\z"),
|
|
612
|
+
None,
|
|
613
|
+
¬hing_is_a_dir,
|
|
614
|
+
);
|
|
615
|
+
assert_eq!(
|
|
616
|
+
t,
|
|
617
|
+
Resolution::Table(PathTable {
|
|
618
|
+
root: PathBuf::from(r"C:\x\a"),
|
|
619
|
+
glob: "*.md".to_string(),
|
|
620
|
+
path_prefix: "C:/x/a".to_string(),
|
|
621
|
+
})
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
#[test]
|
|
626
|
+
fn a_parent_relative_path_past_the_drive_root_stops_there() {
|
|
627
|
+
let t = resolve_as::<Utf8WindowsEncoding>(
|
|
628
|
+
"../../*.md",
|
|
629
|
+
Path::new(r"C:\x"),
|
|
630
|
+
None,
|
|
631
|
+
¬hing_is_a_dir,
|
|
632
|
+
);
|
|
633
|
+
assert_eq!(
|
|
634
|
+
t,
|
|
635
|
+
Resolution::Table(PathTable {
|
|
636
|
+
root: PathBuf::from(r"C:\"),
|
|
637
|
+
glob: "*.md".to_string(),
|
|
638
|
+
path_prefix: "C:/".to_string(),
|
|
639
|
+
})
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
#[test]
|
|
644
|
+
fn a_home_relative_path_resolves_against_the_home_directory() {
|
|
645
|
+
let t = table("~/notes/*.md", ¬hing_is_a_dir);
|
|
646
|
+
assert_eq!(t.root, Path::new(r"C:\Users\u\notes"));
|
|
647
|
+
assert_eq!(t.glob, "*.md");
|
|
648
|
+
assert_eq!(t.path_prefix, "C:/Users/u/notes");
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
#[test]
|
|
652
|
+
fn a_backslash_home_relative_path_resolves_against_the_home_directory() {
|
|
653
|
+
let t = table(r"~\notes\*.md", ¬hing_is_a_dir);
|
|
654
|
+
assert_eq!(t.root, Path::new(r"C:\Users\u\notes"));
|
|
655
|
+
assert_eq!(t.glob, "*.md");
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
#[test]
|
|
659
|
+
fn a_home_relative_path_without_a_home_directory_is_unresolvable() {
|
|
660
|
+
assert_eq!(
|
|
661
|
+
resolve_as::<Utf8WindowsEncoding>(
|
|
662
|
+
r"~\notes",
|
|
663
|
+
Path::new(ROOT),
|
|
664
|
+
None,
|
|
665
|
+
&everything_is_a_dir
|
|
666
|
+
),
|
|
667
|
+
Resolution::NoHome
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
#[test]
|
|
672
|
+
fn a_bare_glob_asks_for_the_dot_slash_form() {
|
|
673
|
+
assert_eq!(resolve_with("**/*.md", ¬hing_is_a_dir), Resolution::Hint);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
#[test]
|
|
677
|
+
fn a_plain_identifier_is_not_a_path() {
|
|
678
|
+
assert_eq!(
|
|
679
|
+
resolve_with("users", ¬hing_is_a_dir),
|
|
680
|
+
Resolution::NotAPath
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
#[test]
|
|
686
|
+
fn a_backslash_after_a_tilde_is_not_a_unix_path() {
|
|
687
|
+
assert_eq!(
|
|
688
|
+
resolve_as::<Utf8UnixEncoding>(
|
|
689
|
+
r"~\notes",
|
|
690
|
+
Path::new(ROOT),
|
|
691
|
+
Some(Path::new("/home/u")),
|
|
692
|
+
¬hing_is_a_dir
|
|
693
|
+
),
|
|
694
|
+
Resolution::NotAPath
|
|
695
|
+
);
|
|
696
|
+
}
|
|
416
697
|
}
|
|
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
|