dirsql 0.3.24__tar.gz → 0.3.25__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.3.24 → dirsql-0.3.25}/Cargo.lock +1 -1
- {dirsql-0.3.24 → dirsql-0.3.25}/PKG-INFO +1 -1
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/config.rs +0 -17
- dirsql-0.3.25/packages/rust/src/scanner.rs +83 -0
- dirsql-0.3.25/packages/rust/tests/config.rs +26 -0
- dirsql-0.3.25/packages/rust/tests/scanner.rs +97 -0
- dirsql-0.3.24/packages/rust/src/scanner.rs +0 -136
- {dirsql-0.3.24 → dirsql-0.3.25}/Cargo.toml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/README.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/_async.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/_async_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/binary_path_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/dispatch_extract.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/dispatch_extract_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/load_app.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/load_app_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/run.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/run_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/write_message.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/interpret/write_message_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/is_windows_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/cli/main_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/py.typed +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/resolve_config.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/dirsql/resolve_config_test.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/AGENTS.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/api/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/cli/config.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/cli/http-api.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/cli/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/cli/init.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/cli/server.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/getting-started.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/async.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/crdt.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/persistence.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/querying.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/tables.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/guide/watching.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/migrations.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/package.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/README.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/conftest.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/api/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/cli/config.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/cli/http-api.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/cli/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/cli/init.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/cli/server.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/async.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/crdt.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/persistence.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/querying.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/tables.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/guide/watching.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/src/lib.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/data/a/meta.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/data/b/meta.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/dirsql.config.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/interpret/data/a/meta.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/interpret/data/b/meta.json +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/interpret/dirsql.config.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/interpret/dirsql.config_no_app.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/interpret/dirsql.config_raises.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/interpret_subprocess.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_async_dirsql.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_binding.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_dirsql.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_docs_examples.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_docs_gaps.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_from_config.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_interpret.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_native_config.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_persist.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/test_serialization.py +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/README.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/api/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/cli/config.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/cli/http-api.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/cli/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/cli/init.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/cli/server.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/async.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/crdt.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/persistence.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/querying.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/tables.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/guide/watching.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/native_config.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/db.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/async_sdk.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/cli_e2e.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/cli_integration.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/code_review_findings.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/docs_examples.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/docs_gaps.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/extensions.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/from_config.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/init_e2e.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/init_integration.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/persist.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/readonly_query.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/sdk.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/serialization.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/packages/rust/tests/watcher.rs +0 -0
- {dirsql-0.3.24 → dirsql-0.3.25}/pyproject.toml +0 -0
|
@@ -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.
|
|
7
|
+
version = "0.3.25"
|
|
8
8
|
edition.workspace = true
|
|
9
9
|
publish = false
|
|
10
10
|
readme = "README.md"
|
|
@@ -256,23 +256,6 @@ glob = "*.json"
|
|
|
256
256
|
assert!(config.ignore.is_empty());
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
#[test]
|
|
260
|
-
fn load_config_from_file() {
|
|
261
|
-
let dir = tempfile::tempdir().unwrap();
|
|
262
|
-
let path = dir.path().join(".dirsql.toml");
|
|
263
|
-
std::fs::write(
|
|
264
|
-
&path,
|
|
265
|
-
r#"
|
|
266
|
-
[[table]]
|
|
267
|
-
ddl = "CREATE TABLE t (_path TEXT)"
|
|
268
|
-
glob = "*.csv"
|
|
269
|
-
"#,
|
|
270
|
-
)
|
|
271
|
-
.unwrap();
|
|
272
|
-
let config = load_config(&path).unwrap();
|
|
273
|
-
assert_eq!(config.tables.len(), 1);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
259
|
#[test]
|
|
277
260
|
fn load_config_missing_file_returns_io_error() {
|
|
278
261
|
let err = load_config(Path::new("/nonexistent/.dirsql.toml")).unwrap_err();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
use crate::matcher::TableMatcher;
|
|
2
|
+
use std::path::{Path, PathBuf};
|
|
3
|
+
use walkdir::WalkDir;
|
|
4
|
+
|
|
5
|
+
/// Top-level directory name reserved for `dirsql`'s own metadata (e.g. the
|
|
6
|
+
/// persistent cache database). Always excluded from the scan, regardless of
|
|
7
|
+
/// whether persistence is enabled.
|
|
8
|
+
pub const RESERVED_DIR: &str = ".dirsql";
|
|
9
|
+
|
|
10
|
+
/// Walk a directory tree and return all file paths paired with their matching table name.
|
|
11
|
+
/// Ignored paths and directories are skipped. Only files (not directories) are returned.
|
|
12
|
+
///
|
|
13
|
+
/// The top-level `.dirsql/` directory is unconditionally excluded.
|
|
14
|
+
pub fn scan_directory(root: &Path, matcher: &TableMatcher) -> Vec<(PathBuf, String)> {
|
|
15
|
+
let mut results = Vec::new();
|
|
16
|
+
|
|
17
|
+
let walker = WalkDir::new(root).into_iter().filter_entry(|entry| {
|
|
18
|
+
// Skip the reserved `.dirsql/` directory at the top level.
|
|
19
|
+
!is_reserved_dir(entry.depth(), entry.file_type().is_dir(), entry.file_name())
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
for entry in walker.filter_map(|e| e.ok()) {
|
|
23
|
+
let path = entry.path();
|
|
24
|
+
|
|
25
|
+
// Match against relative path so globs like "comments/**/*.jsonl" work
|
|
26
|
+
// regardless of the absolute root directory.
|
|
27
|
+
let rel_path = path.strip_prefix(root).unwrap_or(path);
|
|
28
|
+
|
|
29
|
+
if matcher.is_ignored(rel_path) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if !entry.file_type().is_file() {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if let Some(table_name) = matcher.match_file(rel_path) {
|
|
38
|
+
results.push((path.to_path_buf(), table_name.to_string()));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
results
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// True for the reserved top-level `.dirsql/` directory (`depth == 1`), which
|
|
46
|
+
/// the scan unconditionally excludes. Factored out as a pure predicate over the
|
|
47
|
+
/// facts `WalkDir` exposes so it can be unit-tested without walking a real tree
|
|
48
|
+
/// -- the directory-walk behavior itself is covered by `tests/scanner.rs`.
|
|
49
|
+
fn is_reserved_dir(depth: usize, is_dir: bool, file_name: &std::ffi::OsStr) -> bool {
|
|
50
|
+
depth == 1 && is_dir && file_name == RESERVED_DIR
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#[cfg(test)]
|
|
54
|
+
mod tests {
|
|
55
|
+
use super::*;
|
|
56
|
+
use std::ffi::OsStr;
|
|
57
|
+
|
|
58
|
+
// The directory-walk behavior of `scan_directory` (real temp trees, real
|
|
59
|
+
// files) is exercised by `tests/scanner.rs` -- those are integration tests
|
|
60
|
+
// and stay out of this inline unit module, which the `unit lint` isolation
|
|
61
|
+
// rule keeps free of effectful std. What remains here is the pure
|
|
62
|
+
// reserved-dir predicate the walker filters on.
|
|
63
|
+
|
|
64
|
+
#[test]
|
|
65
|
+
fn is_reserved_dir_matches_top_level_dirsql() {
|
|
66
|
+
assert!(is_reserved_dir(1, true, OsStr::new(RESERVED_DIR)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[test]
|
|
70
|
+
fn is_reserved_dir_rejects_nested_dirsql() {
|
|
71
|
+
// Only the *top-level* `.dirsql/` (depth 1) is reserved; a nested one
|
|
72
|
+
// (e.g. `sub/.dirsql/`) is an ordinary directory.
|
|
73
|
+
assert!(!is_reserved_dir(2, true, OsStr::new(RESERVED_DIR)));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#[test]
|
|
77
|
+
fn is_reserved_dir_rejects_files_and_other_names() {
|
|
78
|
+
// A file named `.dirsql` is not the reserved directory ...
|
|
79
|
+
assert!(!is_reserved_dir(1, false, OsStr::new(RESERVED_DIR)));
|
|
80
|
+
// ... and an ordinary top-level directory is not reserved.
|
|
81
|
+
assert!(!is_reserved_dir(1, true, OsStr::new("data")));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//! Integration test for `load_config` reading a real `.dirsql.toml` off disk.
|
|
2
|
+
//!
|
|
3
|
+
//! The pure TOML-parsing tests (`load_config_str`) stay inline in `config.rs`;
|
|
4
|
+
//! this exercises the thin file-reading wrapper, which needs a real file
|
|
5
|
+
//! (effectful std), so per the `unit lint` isolation rule it belongs in the
|
|
6
|
+
//! integration tier rather than the inline unit module.
|
|
7
|
+
|
|
8
|
+
use dirsql::config::load_config;
|
|
9
|
+
use tempfile::TempDir;
|
|
10
|
+
|
|
11
|
+
#[test]
|
|
12
|
+
fn load_config_from_file() {
|
|
13
|
+
let dir = TempDir::new().unwrap();
|
|
14
|
+
let path = dir.path().join(".dirsql.toml");
|
|
15
|
+
std::fs::write(
|
|
16
|
+
&path,
|
|
17
|
+
r#"
|
|
18
|
+
[[table]]
|
|
19
|
+
ddl = "CREATE TABLE t (_path TEXT)"
|
|
20
|
+
glob = "*.csv"
|
|
21
|
+
"#,
|
|
22
|
+
)
|
|
23
|
+
.unwrap();
|
|
24
|
+
let config = load_config(&path).unwrap();
|
|
25
|
+
assert_eq!(config.tables.len(), 1);
|
|
26
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
//! Integration tests for `scan_directory`.
|
|
2
|
+
//!
|
|
3
|
+
//! These build real temp directory trees with real files and assert what the
|
|
4
|
+
//! scanner returns end-to-end through its public API. They were moved out of
|
|
5
|
+
//! `scanner.rs`'s inline `#[cfg(test)]` module so that module stays pure (the
|
|
6
|
+
//! `testing-conventions` `unit lint` isolation rule forbids effectful std --
|
|
7
|
+
//! `std::fs`, temp dirs -- in unit tests). The pure reserved-dir predicate
|
|
8
|
+
//! test remains inline next to the function it covers.
|
|
9
|
+
|
|
10
|
+
use std::fs;
|
|
11
|
+
|
|
12
|
+
use dirsql::matcher::TableMatcher;
|
|
13
|
+
use dirsql::scanner::scan_directory;
|
|
14
|
+
use tempfile::TempDir;
|
|
15
|
+
|
|
16
|
+
#[test]
|
|
17
|
+
fn scan_finds_matching_files() {
|
|
18
|
+
let dir = TempDir::new().unwrap();
|
|
19
|
+
fs::write(dir.path().join("data.csv"), "a,b\n1,2").unwrap();
|
|
20
|
+
fs::write(dir.path().join("readme.md"), "# hi").unwrap();
|
|
21
|
+
|
|
22
|
+
let matcher = TableMatcher::new(&[("**/*.csv", "csv_table")], &[]).unwrap();
|
|
23
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
24
|
+
|
|
25
|
+
assert_eq!(results.len(), 1);
|
|
26
|
+
assert!(results[0].0.ends_with("data.csv"));
|
|
27
|
+
assert_eq!(results[0].1, "csv_table");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#[test]
|
|
31
|
+
fn scan_skips_ignored_files() {
|
|
32
|
+
let dir = TempDir::new().unwrap();
|
|
33
|
+
fs::write(dir.path().join("data.csv"), "a,b").unwrap();
|
|
34
|
+
fs::write(dir.path().join("data.tmp"), "junk").unwrap();
|
|
35
|
+
|
|
36
|
+
let matcher =
|
|
37
|
+
TableMatcher::new(&[("**/*.csv", "t"), ("**/*.tmp", "t2")], &["**/*.tmp"]).unwrap();
|
|
38
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
39
|
+
|
|
40
|
+
assert_eq!(results.len(), 1);
|
|
41
|
+
assert!(results[0].0.ends_with("data.csv"));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[test]
|
|
45
|
+
fn scan_recurses_into_subdirectories() {
|
|
46
|
+
let dir = TempDir::new().unwrap();
|
|
47
|
+
let sub = dir.path().join("nested").join("deep");
|
|
48
|
+
fs::create_dir_all(&sub).unwrap();
|
|
49
|
+
fs::write(sub.join("events.jsonl"), "{}").unwrap();
|
|
50
|
+
|
|
51
|
+
let matcher = TableMatcher::new(&[("**/*.jsonl", "events")], &[]).unwrap();
|
|
52
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
53
|
+
|
|
54
|
+
assert_eq!(results.len(), 1);
|
|
55
|
+
assert!(results[0].0.ends_with("events.jsonl"));
|
|
56
|
+
assert_eq!(results[0].1, "events");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#[test]
|
|
60
|
+
fn scan_returns_empty_for_no_matches() {
|
|
61
|
+
let dir = TempDir::new().unwrap();
|
|
62
|
+
fs::write(dir.path().join("readme.md"), "# hi").unwrap();
|
|
63
|
+
|
|
64
|
+
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
65
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
66
|
+
|
|
67
|
+
assert!(results.is_empty());
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#[test]
|
|
71
|
+
fn scan_skips_directories() {
|
|
72
|
+
let dir = TempDir::new().unwrap();
|
|
73
|
+
// Create a directory that matches the glob -- it should not appear in results
|
|
74
|
+
fs::create_dir(dir.path().join("data.csv")).unwrap();
|
|
75
|
+
|
|
76
|
+
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
77
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
78
|
+
|
|
79
|
+
assert!(results.is_empty());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#[test]
|
|
83
|
+
fn scan_excludes_top_level_dirsql_directory() {
|
|
84
|
+
let dir = TempDir::new().unwrap();
|
|
85
|
+
fs::write(dir.path().join("real.csv"), "a,b\n1,2").unwrap();
|
|
86
|
+
|
|
87
|
+
// Files inside the reserved `.dirsql/` directory (e.g. the cache db)
|
|
88
|
+
// must never be picked up by the scanner.
|
|
89
|
+
fs::create_dir(dir.path().join(".dirsql")).unwrap();
|
|
90
|
+
fs::write(dir.path().join(".dirsql").join("cache.csv"), "a,b\n1,2").unwrap();
|
|
91
|
+
|
|
92
|
+
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
93
|
+
let results = scan_directory(dir.path(), &matcher);
|
|
94
|
+
|
|
95
|
+
assert_eq!(results.len(), 1);
|
|
96
|
+
assert!(results[0].0.ends_with("real.csv"));
|
|
97
|
+
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
use crate::matcher::TableMatcher;
|
|
2
|
-
use std::path::{Path, PathBuf};
|
|
3
|
-
use walkdir::WalkDir;
|
|
4
|
-
|
|
5
|
-
/// Top-level directory name reserved for `dirsql`'s own metadata (e.g. the
|
|
6
|
-
/// persistent cache database). Always excluded from the scan, regardless of
|
|
7
|
-
/// whether persistence is enabled.
|
|
8
|
-
pub const RESERVED_DIR: &str = ".dirsql";
|
|
9
|
-
|
|
10
|
-
/// Walk a directory tree and return all file paths paired with their matching table name.
|
|
11
|
-
/// Ignored paths and directories are skipped. Only files (not directories) are returned.
|
|
12
|
-
///
|
|
13
|
-
/// The top-level `.dirsql/` directory is unconditionally excluded.
|
|
14
|
-
pub fn scan_directory(root: &Path, matcher: &TableMatcher) -> Vec<(PathBuf, String)> {
|
|
15
|
-
let mut results = Vec::new();
|
|
16
|
-
|
|
17
|
-
let walker = WalkDir::new(root).into_iter().filter_entry(|entry| {
|
|
18
|
-
// Skip the reserved `.dirsql/` directory at the top level.
|
|
19
|
-
if entry.depth() == 1 && entry.file_type().is_dir() && entry.file_name() == RESERVED_DIR {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
true
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
for entry in walker.filter_map(|e| e.ok()) {
|
|
26
|
-
let path = entry.path();
|
|
27
|
-
|
|
28
|
-
// Match against relative path so globs like "comments/**/*.jsonl" work
|
|
29
|
-
// regardless of the absolute root directory.
|
|
30
|
-
let rel_path = path.strip_prefix(root).unwrap_or(path);
|
|
31
|
-
|
|
32
|
-
if matcher.is_ignored(rel_path) {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if !entry.file_type().is_file() {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if let Some(table_name) = matcher.match_file(rel_path) {
|
|
41
|
-
results.push((path.to_path_buf(), table_name.to_string()));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
results
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
#[cfg(test)]
|
|
49
|
-
mod tests {
|
|
50
|
-
use super::*;
|
|
51
|
-
use std::fs;
|
|
52
|
-
use tempfile::TempDir;
|
|
53
|
-
|
|
54
|
-
#[test]
|
|
55
|
-
fn scan_finds_matching_files() {
|
|
56
|
-
let dir = TempDir::new().unwrap();
|
|
57
|
-
fs::write(dir.path().join("data.csv"), "a,b\n1,2").unwrap();
|
|
58
|
-
fs::write(dir.path().join("readme.md"), "# hi").unwrap();
|
|
59
|
-
|
|
60
|
-
let matcher = TableMatcher::new(&[("**/*.csv", "csv_table")], &[]).unwrap();
|
|
61
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
62
|
-
|
|
63
|
-
assert_eq!(results.len(), 1);
|
|
64
|
-
assert!(results[0].0.ends_with("data.csv"));
|
|
65
|
-
assert_eq!(results[0].1, "csv_table");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#[test]
|
|
69
|
-
fn scan_skips_ignored_files() {
|
|
70
|
-
let dir = TempDir::new().unwrap();
|
|
71
|
-
fs::write(dir.path().join("data.csv"), "a,b").unwrap();
|
|
72
|
-
fs::write(dir.path().join("data.tmp"), "junk").unwrap();
|
|
73
|
-
|
|
74
|
-
let matcher =
|
|
75
|
-
TableMatcher::new(&[("**/*.csv", "t"), ("**/*.tmp", "t2")], &["**/*.tmp"]).unwrap();
|
|
76
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
77
|
-
|
|
78
|
-
assert_eq!(results.len(), 1);
|
|
79
|
-
assert!(results[0].0.ends_with("data.csv"));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
#[test]
|
|
83
|
-
fn scan_recurses_into_subdirectories() {
|
|
84
|
-
let dir = TempDir::new().unwrap();
|
|
85
|
-
let sub = dir.path().join("nested").join("deep");
|
|
86
|
-
fs::create_dir_all(&sub).unwrap();
|
|
87
|
-
fs::write(sub.join("events.jsonl"), "{}").unwrap();
|
|
88
|
-
|
|
89
|
-
let matcher = TableMatcher::new(&[("**/*.jsonl", "events")], &[]).unwrap();
|
|
90
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
91
|
-
|
|
92
|
-
assert_eq!(results.len(), 1);
|
|
93
|
-
assert!(results[0].0.ends_with("events.jsonl"));
|
|
94
|
-
assert_eq!(results[0].1, "events");
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
#[test]
|
|
98
|
-
fn scan_returns_empty_for_no_matches() {
|
|
99
|
-
let dir = TempDir::new().unwrap();
|
|
100
|
-
fs::write(dir.path().join("readme.md"), "# hi").unwrap();
|
|
101
|
-
|
|
102
|
-
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
103
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
104
|
-
|
|
105
|
-
assert!(results.is_empty());
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
#[test]
|
|
109
|
-
fn scan_skips_directories() {
|
|
110
|
-
let dir = TempDir::new().unwrap();
|
|
111
|
-
// Create a directory that matches the glob -- it should not appear in results
|
|
112
|
-
fs::create_dir(dir.path().join("data.csv")).unwrap();
|
|
113
|
-
|
|
114
|
-
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
115
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
116
|
-
|
|
117
|
-
assert!(results.is_empty());
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
#[test]
|
|
121
|
-
fn scan_excludes_top_level_dirsql_directory() {
|
|
122
|
-
let dir = TempDir::new().unwrap();
|
|
123
|
-
fs::write(dir.path().join("real.csv"), "a,b\n1,2").unwrap();
|
|
124
|
-
|
|
125
|
-
// Files inside the reserved `.dirsql/` directory (e.g. the cache db)
|
|
126
|
-
// must never be picked up by the scanner.
|
|
127
|
-
fs::create_dir(dir.path().join(".dirsql")).unwrap();
|
|
128
|
-
fs::write(dir.path().join(".dirsql").join("cache.csv"), "a,b\n1,2").unwrap();
|
|
129
|
-
|
|
130
|
-
let matcher = TableMatcher::new(&[("**/*.csv", "t")], &[]).unwrap();
|
|
131
|
-
let results = scan_directory(dir.path(), &matcher);
|
|
132
|
-
|
|
133
|
-
assert_eq!(results.len(), 1);
|
|
134
|
-
assert!(results[0].0.ends_with("real.csv"));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
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
|
|
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.3.24 → dirsql-0.3.25}/packages/python/docs/tests/integration/language-flag.spec.ts
RENAMED
|
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.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/data/a/meta.json
RENAMED
|
File without changes
|
{dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/data/b/meta.json
RENAMED
|
File without changes
|
{dirsql-0.3.24 → dirsql-0.3.25}/packages/python/tests/integration/__fixtures__/dirsql.config.py
RENAMED
|
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
|
|
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
|