kodit 0.2.5__tar.gz → 0.2.7__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.
Potentially problematic release.
This version of kodit might be problematic. Click here for more details.
- {kodit-0.2.5 → kodit-0.2.7}/PKG-INFO +1 -1
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/configuration/index.md +1 -1
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/deployment/index.md +1 -2
- kodit-0.2.7/docs/reference/indexing/index.md +279 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/_version.py +2 -2
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/services/indexing_application_service.py +26 -2
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/services/snippet_application_service.py +6 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/cli.py +14 -1
- kodit-0.2.7/src/kodit/domain/errors.py +5 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/source_service.py +5 -3
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/folder/factory.py +10 -1
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/git/factory.py +27 -7
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/git/working_copy.py +12 -4
- kodit-0.2.7/src/kodit/infrastructure/git/git_utils.py +87 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/indexing/index_repository.py +0 -5
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/indexing/indexing_factory.py +2 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/sqlalchemy/embedding_repository.py +0 -2
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/sqlalchemy/file_repository.py +19 -14
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/sqlalchemy/repository.py +51 -39
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/sqlalchemy/snippet_repository.py +15 -11
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/mcp.py +1 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/application/indexing_application_service_test.py +60 -1
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/application/snippet_application_service_test.py +13 -0
- kodit-0.2.7/tests/kodit/infrastructure/cloning/git/factory_test.py +225 -0
- kodit-0.2.7/tests/kodit/infrastructure/cloning/git/working_copy_test.py +168 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/test_enrichment_integration.py +19 -6
- kodit-0.2.7/tests/kodit/infrastructure/git/test_git_utils.py +127 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/sqlalchemy/test_embedding_repository.py +1 -1
- kodit-0.2.5/src/kodit/infrastructure/git/git_utils.py +0 -24
- {kodit-0.2.5 → kodit-0.2.7}/.cursor/rules/kodit.mdc +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.dockerignore +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/CODE_OF_CONDUCT.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/CONTRIBUTING.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/dependabot.yml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/docker.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/docs.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/pull_request.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/pypi-test.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/pypi.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.github/workflows/test.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.gitignore +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.python-version +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.vscode/launch.json +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/.vscode/settings.json +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/Dockerfile +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/LICENSE +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/README.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/alembic.ini +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/_index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/demos/_index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/demos/go-simple-microservice/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/demos/knock-knock-auth/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/developer/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/getting-started/_index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/getting-started/installation/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/getting-started/integration/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/getting-started/quick-start/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/_index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/deployment/docker-compose.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/deployment/kubernetes.yaml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/docs/reference/telemetry/index.md +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/pyproject.toml +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/.gitignore +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/app.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/commands/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/commands/snippet_commands.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/application/services/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/config.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/database.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/entities.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/enums.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/interfaces.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/repositories.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/bm25_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/embedding_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/enrichment_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/ignore_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/indexing_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/services/snippet_extraction_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/domain/value_objects.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/bm25/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/bm25/bm25_factory.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/bm25/local_bm25_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/bm25/vectorchord_bm25_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/folder/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/folder/working_copy.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/git/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/cloning/metadata.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_factory.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_providers/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_providers/batching.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_providers/hash_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_providers/local_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/embedding_providers/openai_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/local_vector_search_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/embedding/vectorchord_vector_search_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/enrichment_factory.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/legacy_enrichment_models.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/local_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/enrichment/openai_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/git/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/ignore/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/ignore/ignore_pattern_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/indexing/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/indexing/fusion_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/language_detection_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/languages/csharp.scm +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/languages/go.scm +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/languages/javascript.scm +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/languages/python.scm +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/languages/typescript.scm +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/snippet_extraction_factory.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/snippet_query_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/snippet_extraction/tree_sitter_snippet_extractor.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/sqlalchemy/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/ui/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/ui/progress.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/infrastructure/ui/spinner.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/log.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/middleware.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/README +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/env.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/script.py.mako +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/versions/7c3bbc2ab32b_add_embeddings_table.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/versions/85155663351e_initial.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/versions/9e53ea8bb3b0_add_authors.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/versions/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/migrations/versions/c3f5137d30f5_index_all_the_things.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/src/kodit/reporting.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/conftest.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/docker-smoke.sh +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/experiments/cline-prompt-regression-tests/cline_prompt.txt +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/experiments/cline-prompt-regression-tests/cline_prompt_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/experiments/embedding.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/experiments/similarity_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/application/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/cli_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/bm25_domain_service_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/enrichment_domain_service_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/snippet_extraction_domain_service_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/test_embedding_service.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/domain/test_models.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/e2e.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/embedding_factory_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/embedding_provider/test_hash_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/embedding_provider/test_local_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/embedding_provider/test_openai_embedding_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/test_batching.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/test_embedding_integration.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/test_local_vector_search_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/embedding/test_vectorchord_vector_search_repository.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/enrichment_provider/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/enrichment_provider/test_local_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/enrichment_provider/test_null_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/enrichment_provider/test_openai_enrichment_provider.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/enrichment/test_enrichment_factory.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/indexing/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/indexing/indexing_repository_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/csharp.cs +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/golang.go +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/javascript.js +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/knock-knock-server.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/python.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/snippets/typescript.tsx +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/source/__init__.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/infrastructure/source/source_service_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/log_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/kodit/mcp_test.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/performance/similarity.py +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/smoke.sh +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/tests/vectorchord-smoke.sh +0 -0
- {kodit-0.2.5 → kodit-0.2.7}/uv.lock +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Deployment
|
|
3
3
|
description: Deploying Kodit with Docker Compose and Kubernetes.
|
|
4
|
-
weight:
|
|
4
|
+
weight: 20
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Kodit is packaged as a Docker container so you can run it on any popular orchestration platform. This page describes how to deploy Kodit as a service.
|
|
@@ -32,4 +32,3 @@ Deploy with `kubectl -n kodit apply -f kubernetes.yaml`
|
|
|
32
32
|
|
|
33
33
|
1. `kind create cluster`
|
|
34
34
|
2. `kubectl -n kodit apply -f kubernetes.yaml`
|
|
35
|
-
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Indexing
|
|
3
|
+
description: Learn how to index code sources in Kodit for AI-powered code search and generation.
|
|
4
|
+
weight: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Kodit's indexing system allows you to create searchable indexes of your codebases, enabling AI assistants to find and reference relevant code snippets. This page explains how indexing works, what sources are supported, and how to use the indexing features.
|
|
8
|
+
|
|
9
|
+
## How Indexing Works
|
|
10
|
+
|
|
11
|
+
Kodit's indexing process consists of several stages:
|
|
12
|
+
|
|
13
|
+
1. **Source Creation**: Kodit clones or copies your source code to a local working directory
|
|
14
|
+
2. **File Processing**: Files are scanned and metadata is extracted (timestamps, authors, etc.)
|
|
15
|
+
3. **Snippet Extraction**: Code is parsed using tree-sitter to extract meaningful snippets (functions, classes, methods)
|
|
16
|
+
4. **Index Building**: Multiple search indexes are created:
|
|
17
|
+
- **BM25 Index**: For keyword-based search
|
|
18
|
+
- **Semantic Code Index**: For code similarity search using embeddings
|
|
19
|
+
5. **Enrichment**: AI-powered enrichment of snippets for better search results
|
|
20
|
+
- **Semantic Text Index**: For natural language search using embeddings
|
|
21
|
+
|
|
22
|
+
### Supported Source Types
|
|
23
|
+
|
|
24
|
+
Kodit supports two main types of sources:
|
|
25
|
+
|
|
26
|
+
#### Git Repositories
|
|
27
|
+
|
|
28
|
+
Kodit can index any Git repository accessible via standard Git protocols:
|
|
29
|
+
|
|
30
|
+
- **HTTPS**: Public repositories and private repositories with authentication
|
|
31
|
+
- **SSH**: Using SSH keys for authentication
|
|
32
|
+
- **Git Protocol**: For public repositories
|
|
33
|
+
|
|
34
|
+
#### Local Directories
|
|
35
|
+
|
|
36
|
+
Kodit can index local directories on your filesystem:
|
|
37
|
+
|
|
38
|
+
- **Absolute paths**: `/path/to/your/code`
|
|
39
|
+
- **Relative paths**: `./my-project`
|
|
40
|
+
- **Home directory expansion**: `~/projects/my-app`
|
|
41
|
+
- **File URIs**: `file:///path/to/your/code`
|
|
42
|
+
|
|
43
|
+
## Basic Usage
|
|
44
|
+
|
|
45
|
+
### Indexing a Source
|
|
46
|
+
|
|
47
|
+
To index a source, use the `kodit index` command followed by the source location:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
# Index a local directory
|
|
51
|
+
kodit index /path/to/your/code
|
|
52
|
+
|
|
53
|
+
# Index a public Git repository
|
|
54
|
+
kodit index https://github.com/pydantic/pydantic
|
|
55
|
+
|
|
56
|
+
# Index a private Git repository (requires authentication)
|
|
57
|
+
kodit index https://github.com/username/private-repo
|
|
58
|
+
|
|
59
|
+
# Index using SSH
|
|
60
|
+
kodit index git@github.com:username/repo.git
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Listing Indexes
|
|
64
|
+
|
|
65
|
+
To see all your indexed sources:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
kodit index
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This will display a table showing:
|
|
72
|
+
|
|
73
|
+
- Index ID
|
|
74
|
+
- Creation and update timestamps
|
|
75
|
+
- Source URI
|
|
76
|
+
- Number of snippets extracted
|
|
77
|
+
|
|
78
|
+
## Git Protocol Support
|
|
79
|
+
|
|
80
|
+
### HTTPS Authentication
|
|
81
|
+
|
|
82
|
+
For private repositories, you can authenticate using:
|
|
83
|
+
|
|
84
|
+
1. **Personal Access Token** (GitHub, GitLab, etc.):
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
kodit index https://username:token@github.com/username/repo.git
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
2. **Username/Password** (if supported by your Git provider):
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
kodit index https://username:password@github.com/username/repo.git
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### SSH Authentication
|
|
97
|
+
|
|
98
|
+
For SSH-based repositories:
|
|
99
|
+
|
|
100
|
+
1. **SSH Key Authentication**:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
kodit index git@github.com:username/repo.git
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Ensure your SSH key is properly configured in your SSH agent or `~/.ssh/config`.
|
|
107
|
+
|
|
108
|
+
2. **SSH with Custom Port**:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
kodit index ssh://git@github.com:2222/username/repo.git
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Git Providers
|
|
115
|
+
|
|
116
|
+
Kodit works with any Git provider that supports standard Git protocols:
|
|
117
|
+
|
|
118
|
+
- **GitHub**: `https://github.com/username/repo.git`
|
|
119
|
+
- **GitLab**: `https://gitlab.com/username/repo.git`
|
|
120
|
+
- **Bitbucket**: `https://bitbucket.org/username/repo.git`
|
|
121
|
+
- **Azure DevOps**: `https://dev.azure.com/organization/project/_git/repo`
|
|
122
|
+
- **Self-hosted Git servers**: Any Git server supporting HTTP/HTTPS or SSH
|
|
123
|
+
|
|
124
|
+
## Examples of Use
|
|
125
|
+
|
|
126
|
+
### Index a Public Azure DevOps Repository
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
kodit index https://winderai@dev.azure.com/winderai/public-test/_git/simple-ddd-brewing-demo
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Indexing a Private Azure DevOps Repository
|
|
133
|
+
|
|
134
|
+
If you're accessing Azure DevOps from your local machine and have the Git credential
|
|
135
|
+
helper you should be able to clone the repository as usual (obviously you won't be able
|
|
136
|
+
to clone this because it is private):
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
kodit index https://winderai@dev.azure.com/winderai/private-test/_git/private-test
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
You can also use a Personal Access Token (PAT):
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
kodit index https://phil:xxxxxxSECRET_PATxxxxxxx@dev.azure.com/winderai/private-test/_git/private-test
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## File Processing and Filtering
|
|
149
|
+
|
|
150
|
+
### Ignored Files
|
|
151
|
+
|
|
152
|
+
Kodit respects [standard ignore patterns](#ignore-patterns):
|
|
153
|
+
|
|
154
|
+
- **`.gitignore`**: Standard Git ignore patterns
|
|
155
|
+
- **`.noindex`**: Custom ignore patterns for Kodit (uses gitignore syntax)
|
|
156
|
+
|
|
157
|
+
### Supported File Types
|
|
158
|
+
|
|
159
|
+
Kodit automatically detects and processes files based on their extensions:
|
|
160
|
+
|
|
161
|
+
| Language | Extensions |
|
|
162
|
+
|----------|------------|
|
|
163
|
+
| Python | `.py` |
|
|
164
|
+
| JavaScript | `.js`, `.jsx` |
|
|
165
|
+
| TypeScript | `.ts`, `.tsx` |
|
|
166
|
+
| Go | `.go` |
|
|
167
|
+
| C# | `.cs` |
|
|
168
|
+
|
|
169
|
+
### Snippet Extraction
|
|
170
|
+
|
|
171
|
+
Kodit uses tree-sitter to intelligently extract code snippets:
|
|
172
|
+
|
|
173
|
+
- **Functions and Methods**: Complete function definitions with their bodies
|
|
174
|
+
- **Classes**: Class definitions and their methods
|
|
175
|
+
- **Imports**: Import statements for context
|
|
176
|
+
- **Dependencies**: Ancestor classes and functions that the snippet depends on
|
|
177
|
+
|
|
178
|
+
## Configuration
|
|
179
|
+
|
|
180
|
+
### Clone Directory
|
|
181
|
+
|
|
182
|
+
By default, Kodit stores cloned repositories in `~/.kodit/clones/`. You can configure this using the `DATA_DIR` environment variable:
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
export DATA_DIR=/custom/path/to/kodit/data
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Database Configuration
|
|
189
|
+
|
|
190
|
+
Kodit uses SQLite by default, but supports PostgreSQL with VectorChord for better performance:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
# SQLite (default)
|
|
194
|
+
DB_URL=sqlite+aiosqlite:///path/to/kodit.db
|
|
195
|
+
|
|
196
|
+
# PostgreSQL with VectorChord
|
|
197
|
+
DB_URL=postgresql+asyncpg://user:password@localhost:5432/kodit
|
|
198
|
+
DEFAULT_SEARCH_PROVIDER=vectorchord
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### AI Provider Configuration
|
|
202
|
+
|
|
203
|
+
For semantic search and enrichment, configure your AI provider:
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
# OpenAI
|
|
207
|
+
DEFAULT_ENDPOINT_TYPE=openai
|
|
208
|
+
DEFAULT_ENDPOINT_BASE_URL=https://api.openai.com/v1
|
|
209
|
+
DEFAULT_ENDPOINT_API_KEY=sk-your-api-key
|
|
210
|
+
|
|
211
|
+
# Or use local models (slower but private)
|
|
212
|
+
# No configuration needed - uses local models by default
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Advanced Features
|
|
216
|
+
|
|
217
|
+
### Re-indexing Sources
|
|
218
|
+
|
|
219
|
+
Future feature!
|
|
220
|
+
|
|
221
|
+
### Progress Monitoring
|
|
222
|
+
|
|
223
|
+
Kodit shows progress during indexing operations:
|
|
224
|
+
|
|
225
|
+
- File processing progress
|
|
226
|
+
- Snippet extraction progress
|
|
227
|
+
- Index building progress (BM25, embeddings)
|
|
228
|
+
|
|
229
|
+
### Error Handling
|
|
230
|
+
|
|
231
|
+
Common issues and solutions:
|
|
232
|
+
|
|
233
|
+
1. **Authentication Errors**: Ensure your credentials are correct
|
|
234
|
+
2. **Network Issues**: Check your internet connection and firewall settings
|
|
235
|
+
3. **Permission Errors**: Ensure you have read access to the source
|
|
236
|
+
4. **Unsupported Files**: Kodit will skip unsupported file types automatically
|
|
237
|
+
|
|
238
|
+
## Privacy and Security
|
|
239
|
+
|
|
240
|
+
### Local Processing
|
|
241
|
+
|
|
242
|
+
- All code is processed locally by default
|
|
243
|
+
- No code is sent to external services unless you configure AI providers
|
|
244
|
+
- Cloned repositories are stored locally in your data directory
|
|
245
|
+
|
|
246
|
+
### Ignore Patterns
|
|
247
|
+
|
|
248
|
+
Kodit respects privacy by honoring:
|
|
249
|
+
|
|
250
|
+
- `.gitignore` patterns
|
|
251
|
+
- `.noindex` files for custom exclusions
|
|
252
|
+
- Hidden files and directories (starting with `.`)
|
|
253
|
+
|
|
254
|
+
### Authentication
|
|
255
|
+
|
|
256
|
+
- SSH keys and tokens are handled by your system's Git configuration
|
|
257
|
+
- Kodit doesn't store or transmit credentials
|
|
258
|
+
- Use environment variables for sensitive configuration
|
|
259
|
+
|
|
260
|
+
## Troubleshooting
|
|
261
|
+
|
|
262
|
+
### Common Issues
|
|
263
|
+
|
|
264
|
+
1. **"Failed to clone repository"**: Check your Git credentials and network connection
|
|
265
|
+
2. **"Unsupported source"**: Ensure the path or URL is valid and accessible
|
|
266
|
+
3. **"No snippets found"**: Check if the source contains supported file types
|
|
267
|
+
4. **"Permission denied"**: Ensure you have read access to the source
|
|
268
|
+
|
|
269
|
+
### Checking Index Status
|
|
270
|
+
|
|
271
|
+
To verify your indexes are working correctly:
|
|
272
|
+
|
|
273
|
+
```sh
|
|
274
|
+
# List all indexes
|
|
275
|
+
kodit index
|
|
276
|
+
|
|
277
|
+
# Test search functionality
|
|
278
|
+
kodit search text "example function"
|
|
279
|
+
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Application service for indexing operations."""
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
4
5
|
|
|
5
6
|
from kodit.application.commands.snippet_commands import CreateIndexSnippetsCommand
|
|
6
7
|
from kodit.application.services.snippet_application_service import (
|
|
@@ -8,6 +9,7 @@ from kodit.application.services.snippet_application_service import (
|
|
|
8
9
|
)
|
|
9
10
|
from kodit.domain.entities import Snippet
|
|
10
11
|
from kodit.domain.enums import SnippetExtractionStrategy
|
|
12
|
+
from kodit.domain.errors import EmptySourceError
|
|
11
13
|
from kodit.domain.interfaces import ProgressCallback
|
|
12
14
|
from kodit.domain.services.bm25_service import BM25DomainService
|
|
13
15
|
from kodit.domain.services.embedding_service import EmbeddingDomainService
|
|
@@ -51,6 +53,7 @@ class IndexingApplicationService:
|
|
|
51
53
|
text_search_service: EmbeddingDomainService,
|
|
52
54
|
enrichment_service: EnrichmentDomainService,
|
|
53
55
|
snippet_application_service: SnippetApplicationService,
|
|
56
|
+
session: AsyncSession,
|
|
54
57
|
) -> None:
|
|
55
58
|
"""Initialize the indexing application service.
|
|
56
59
|
|
|
@@ -62,11 +65,13 @@ class IndexingApplicationService:
|
|
|
62
65
|
text_search_service: The text search domain service.
|
|
63
66
|
enrichment_service: The enrichment domain service.
|
|
64
67
|
snippet_application_service: The snippet application service.
|
|
68
|
+
session: The database session for transaction management.
|
|
65
69
|
|
|
66
70
|
"""
|
|
67
71
|
self.indexing_domain_service = indexing_domain_service
|
|
68
72
|
self.source_service = source_service
|
|
69
73
|
self.snippet_application_service = snippet_application_service
|
|
74
|
+
self.session = session
|
|
70
75
|
self.log = structlog.get_logger(__name__)
|
|
71
76
|
self.bm25_service = bm25_service
|
|
72
77
|
self.code_search_service = code_search_service
|
|
@@ -93,7 +98,12 @@ class IndexingApplicationService:
|
|
|
93
98
|
|
|
94
99
|
# Create the index
|
|
95
100
|
request = IndexCreateRequest(source_id=source.id)
|
|
96
|
-
|
|
101
|
+
index_view = await self.indexing_domain_service.create_index(request)
|
|
102
|
+
|
|
103
|
+
# Commit the index creation
|
|
104
|
+
await self.session.commit()
|
|
105
|
+
|
|
106
|
+
return index_view
|
|
97
107
|
|
|
98
108
|
async def list_indexes(self) -> list[IndexView]:
|
|
99
109
|
"""List all available indexes with their details.
|
|
@@ -125,7 +135,7 @@ class IndexingApplicationService:
|
|
|
125
135
|
progress_callback: Optional progress callback for reporting progress.
|
|
126
136
|
|
|
127
137
|
Raises:
|
|
128
|
-
ValueError: If the index doesn't exist.
|
|
138
|
+
ValueError: If the index doesn't exist or no indexable snippets are found.
|
|
129
139
|
|
|
130
140
|
"""
|
|
131
141
|
log_event("kodit.index.run")
|
|
@@ -138,8 +148,11 @@ class IndexingApplicationService:
|
|
|
138
148
|
|
|
139
149
|
# Delete old snippets so we don't duplicate
|
|
140
150
|
await self.indexing_domain_service.delete_all_snippets(index.id)
|
|
151
|
+
# Commit the deletion
|
|
152
|
+
await self.session.commit()
|
|
141
153
|
|
|
142
154
|
# Create snippets for supported file types using the snippet application service
|
|
155
|
+
# (snippet_application_service handles its own commits)
|
|
143
156
|
self.log.info("Creating snippets for files", index_id=index.id)
|
|
144
157
|
command = CreateIndexSnippetsCommand(
|
|
145
158
|
index_id=index.id, strategy=SnippetExtractionStrategy.METHOD_BASED
|
|
@@ -150,6 +163,11 @@ class IndexingApplicationService:
|
|
|
150
163
|
|
|
151
164
|
snippets = await self.indexing_domain_service.get_snippets_for_index(index.id)
|
|
152
165
|
|
|
166
|
+
# Check if any snippets were extracted
|
|
167
|
+
if not snippets:
|
|
168
|
+
msg = f"No indexable snippets found for index {index.id}"
|
|
169
|
+
raise EmptySourceError(msg)
|
|
170
|
+
|
|
153
171
|
# Create BM25 index
|
|
154
172
|
self.log.info("Creating keyword index")
|
|
155
173
|
reporter = Reporter(self.log, progress_callback)
|
|
@@ -184,6 +202,8 @@ class IndexingApplicationService:
|
|
|
184
202
|
|
|
185
203
|
# Update index timestamp
|
|
186
204
|
await self.indexing_domain_service.update_index_timestamp(index.id)
|
|
205
|
+
# Commit the timestamp update
|
|
206
|
+
await self.session.commit()
|
|
187
207
|
|
|
188
208
|
async def _create_bm25_index(
|
|
189
209
|
self, snippets: list[Snippet], progress_callback: ProgressCallback | None = None
|
|
@@ -264,6 +284,10 @@ class IndexingApplicationService:
|
|
|
264
284
|
"enrichment", processed, len(snippets), "Enriching snippets..."
|
|
265
285
|
)
|
|
266
286
|
|
|
287
|
+
# Commit all snippet content updates as a single transaction
|
|
288
|
+
if enriched_contents:
|
|
289
|
+
await self.session.commit()
|
|
290
|
+
|
|
267
291
|
await reporter.done("enrichment")
|
|
268
292
|
|
|
269
293
|
async def _create_text_embeddings(
|
|
@@ -4,6 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
7
8
|
|
|
8
9
|
from kodit.application.commands.snippet_commands import (
|
|
9
10
|
CreateIndexSnippetsCommand,
|
|
@@ -28,6 +29,7 @@ class SnippetApplicationService:
|
|
|
28
29
|
snippet_extraction_service: SnippetExtractionDomainService,
|
|
29
30
|
snippet_repository: SnippetRepository,
|
|
30
31
|
file_repository: FileRepository,
|
|
32
|
+
session: AsyncSession,
|
|
31
33
|
) -> None:
|
|
32
34
|
"""Initialize the snippet application service.
|
|
33
35
|
|
|
@@ -35,11 +37,13 @@ class SnippetApplicationService:
|
|
|
35
37
|
snippet_extraction_service: Domain service for snippet extraction
|
|
36
38
|
snippet_repository: Repository for snippet persistence
|
|
37
39
|
file_repository: Repository for file operations
|
|
40
|
+
session: The database session for transaction management
|
|
38
41
|
|
|
39
42
|
"""
|
|
40
43
|
self.snippet_extraction_service = snippet_extraction_service
|
|
41
44
|
self.snippet_repository = snippet_repository
|
|
42
45
|
self.file_repository = file_repository
|
|
46
|
+
self.session = session
|
|
43
47
|
self.log = structlog.get_logger(__name__)
|
|
44
48
|
|
|
45
49
|
async def extract_snippets_from_file(
|
|
@@ -140,4 +144,6 @@ class SnippetApplicationService:
|
|
|
140
144
|
message=f"Processing {file.cloned_path}...",
|
|
141
145
|
)
|
|
142
146
|
|
|
147
|
+
# Commit all snippet creations in a single transaction
|
|
148
|
+
await self.session.commit()
|
|
143
149
|
await reporter.done("create_snippets")
|
|
@@ -19,6 +19,7 @@ from kodit.config import (
|
|
|
19
19
|
with_app_context,
|
|
20
20
|
with_session,
|
|
21
21
|
)
|
|
22
|
+
from kodit.domain.errors import EmptySourceError
|
|
22
23
|
from kodit.domain.services.source_service import SourceService
|
|
23
24
|
from kodit.domain.value_objects import MultiSearchRequest
|
|
24
25
|
from kodit.infrastructure.indexing.indexing_factory import (
|
|
@@ -58,6 +59,7 @@ def create_snippet_application_service(
|
|
|
58
59
|
snippet_extraction_service=snippet_extraction_service,
|
|
59
60
|
snippet_repository=snippet_repository,
|
|
60
61
|
file_repository=file_repository,
|
|
62
|
+
session=session,
|
|
61
63
|
)
|
|
62
64
|
|
|
63
65
|
|
|
@@ -100,6 +102,7 @@ async def index(
|
|
|
100
102
|
sources: list[str],
|
|
101
103
|
) -> None:
|
|
102
104
|
"""List indexes, or index data sources."""
|
|
105
|
+
log = structlog.get_logger(__name__)
|
|
103
106
|
source_service = SourceService(
|
|
104
107
|
clone_dir=app_context.get_clone_dir(),
|
|
105
108
|
session_factory=lambda: session,
|
|
@@ -152,7 +155,17 @@ async def index(
|
|
|
152
155
|
|
|
153
156
|
# Create a new progress callback for the indexing operations
|
|
154
157
|
indexing_progress_callback = create_multi_stage_progress_callback()
|
|
155
|
-
|
|
158
|
+
try:
|
|
159
|
+
await service.run_index(index.id, indexing_progress_callback)
|
|
160
|
+
except EmptySourceError as e:
|
|
161
|
+
log.exception("Empty source error", error=e)
|
|
162
|
+
msg = f"""{e}. This could mean:
|
|
163
|
+
• The repository contains no supported file types
|
|
164
|
+
• All files are excluded by ignore patterns
|
|
165
|
+
• The files contain no extractable code snippets
|
|
166
|
+
Please check the repository contents and try again.
|
|
167
|
+
"""
|
|
168
|
+
click.echo(msg)
|
|
156
169
|
|
|
157
170
|
|
|
158
171
|
@cli.group()
|
|
@@ -49,7 +49,7 @@ class SourceService:
|
|
|
49
49
|
"""Create a source."""
|
|
50
50
|
async with self._session_factory() as session:
|
|
51
51
|
repo = SqlAlchemySourceRepository(session)
|
|
52
|
-
git_factory, folder_factory = self._build_factories(repo)
|
|
52
|
+
git_factory, folder_factory = self._build_factories(repo, session)
|
|
53
53
|
|
|
54
54
|
if is_valid_clone_target(uri_or_path_like):
|
|
55
55
|
source = await git_factory.create(uri_or_path_like, progress_callback)
|
|
@@ -60,17 +60,18 @@ class SourceService:
|
|
|
60
60
|
else:
|
|
61
61
|
raise ValueError(f"Unsupported source: {uri_or_path_like}")
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
# Factories handle their own commits now
|
|
64
64
|
return source
|
|
65
65
|
|
|
66
66
|
def _build_factories(
|
|
67
|
-
self, repository: SourceRepository
|
|
67
|
+
self, repository: SourceRepository, session: AsyncSession
|
|
68
68
|
) -> tuple[GitSourceFactory, FolderSourceFactory]:
|
|
69
69
|
# Git-specific collaborators
|
|
70
70
|
git_wc = GitWorkingCopyProvider(self.clone_dir)
|
|
71
71
|
git_factory = GitSourceFactory(
|
|
72
72
|
repository=repository,
|
|
73
73
|
working_copy=git_wc,
|
|
74
|
+
session=session,
|
|
74
75
|
)
|
|
75
76
|
|
|
76
77
|
# Folder-specific collaborators
|
|
@@ -78,6 +79,7 @@ class SourceService:
|
|
|
78
79
|
folder_factory = FolderSourceFactory(
|
|
79
80
|
repository=repository,
|
|
80
81
|
working_copy=fold_wc,
|
|
82
|
+
session=session,
|
|
81
83
|
)
|
|
82
84
|
|
|
83
85
|
return git_factory, folder_factory
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import structlog
|
|
6
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
6
7
|
|
|
7
8
|
from kodit.domain.entities import AuthorFileMapping, Source, SourceType
|
|
8
9
|
from kodit.domain.interfaces import NullProgressCallback, ProgressCallback
|
|
@@ -22,6 +23,7 @@ class FolderSourceFactory:
|
|
|
22
23
|
self,
|
|
23
24
|
repository: SourceRepository,
|
|
24
25
|
working_copy: FolderWorkingCopyProvider,
|
|
26
|
+
session: AsyncSession,
|
|
25
27
|
) -> None:
|
|
26
28
|
"""Initialize the source factory."""
|
|
27
29
|
self.log = structlog.get_logger(__name__)
|
|
@@ -29,6 +31,7 @@ class FolderSourceFactory:
|
|
|
29
31
|
self.working_copy = working_copy
|
|
30
32
|
self.metadata_extractor = FolderFileMetadataExtractor()
|
|
31
33
|
self.author_extractor = NoOpAuthorExtractor()
|
|
34
|
+
self.session = session
|
|
32
35
|
|
|
33
36
|
async def create(
|
|
34
37
|
self, uri: str, progress_callback: ProgressCallback | None = None
|
|
@@ -55,7 +58,7 @@ class FolderSourceFactory:
|
|
|
55
58
|
clone_path = await self.working_copy.prepare(directory.as_uri())
|
|
56
59
|
|
|
57
60
|
# Create source record
|
|
58
|
-
source = await self.repository.
|
|
61
|
+
source = await self.repository.save(
|
|
59
62
|
Source(
|
|
60
63
|
uri=directory.as_uri(),
|
|
61
64
|
cloned_path=str(clone_path),
|
|
@@ -63,12 +66,18 @@ class FolderSourceFactory:
|
|
|
63
66
|
)
|
|
64
67
|
)
|
|
65
68
|
|
|
69
|
+
# Commit source creation so we get an ID for foreign key relationships
|
|
70
|
+
await self.session.commit()
|
|
71
|
+
|
|
66
72
|
# Get all files to process
|
|
67
73
|
files = [f for f in clone_path.rglob("*") if f.is_file()]
|
|
68
74
|
|
|
69
75
|
# Process files
|
|
70
76
|
await self._process_files(source, files, progress_callback)
|
|
71
77
|
|
|
78
|
+
# Commit file processing
|
|
79
|
+
await self.session.commit()
|
|
80
|
+
|
|
72
81
|
return source
|
|
73
82
|
|
|
74
83
|
async def _process_files(
|