minder-cli 0.3.8__tar.gz → 0.4.0__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.
- {minder_cli-0.3.8 → minder_cli-0.4.0}/PKG-INFO +1 -1
- {minder_cli-0.3.8 → minder_cli-0.4.0}/pyproject.toml +1 -1
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/commands/update.py +7 -7
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/utils/version.py +15 -2
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/repo_scanner.py +38 -41
- {minder_cli-0.3.8 → minder_cli-0.4.0}/.gitignore +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/LICENSE +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/README-pypi.md +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/README.md +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/api/routers/prompts.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/application/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/application/admin/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/application/admin/dto.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/application/admin/jobs.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/application/admin/use_cases.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/context.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/middleware.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/principal.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/rate_limiter.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/rbac.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/auth/service.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/bootstrap/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/bootstrap/providers.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/bootstrap/transport.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/cache/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/cache/providers.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/chunking/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/chunking/code_splitter.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/chunking/splitter.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/cli.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/config.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/continuity.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/dev.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/embedding/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/embedding/base.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/embedding/local.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/embedding/openai.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/edges.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/executor.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/graph.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/evaluator.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/guard.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/llm.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/planning.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/reasoning.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/reranker.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/retriever.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/verification.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/nodes/workflow_planner.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/runtime.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/graph/state.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/llm/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/llm/base.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/llm/factory.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/llm/litert.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/llm/openai.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/base.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/client.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/document.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/error.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/graph.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/history.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/job.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/prompt.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/repository.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/rule.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/session.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/skill.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/user.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/models/workflow.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/observability/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/observability/audit.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/observability/logging.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/observability/metrics.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/observability/tracing.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/commands/auth.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/commands/ide.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/commands/mcp.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/commands/sync.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/main.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/utils/common.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/utils/config.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/cli/utils/git.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/api.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/context.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/dashboard.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/jobs.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/memories.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/prompts.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/routes.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/runtime.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/search.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/presentation/http/admin/skills.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/prompts/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/prompts/formatter.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/resources/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/retrieval/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/retrieval/hybrid.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/retrieval/mmr.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/retrieval/multi_hop.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/runtime.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/server.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/document.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/error.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/feedback.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/graph.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/history.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/interfaces.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/milvus/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/milvus/client.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/milvus/collections.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/milvus/vector_store.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/mongodb/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/mongodb/client.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/mongodb/indexes.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/mongodb/operational_store.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/relational.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/repo_state.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/rule.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/store/vector.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/auth.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/graph.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/ingest.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/memory.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/query.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/registry.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/search.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/session.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/skills.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/tools/workflow.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/transport/__init__.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/transport/base.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/transport/sse.py +0 -0
- {minder_cli-0.3.8 → minder_cli-0.4.0}/src/minder/transport/stdio.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: minder-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Minder CLI is the command-line interface for the Minder self-hosted MCP platform.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hiimtrung/minder
|
|
6
6
|
Project-URL: Repository, https://github.com/hiimtrung/minder
|
|
@@ -35,7 +35,7 @@ def version_command(args: argparse.Namespace) -> int:
|
|
|
35
35
|
else:
|
|
36
36
|
print(" status: up to date")
|
|
37
37
|
else:
|
|
38
|
-
print("minder version unknown (not installed as a package)")
|
|
38
|
+
print("minder-cli version unknown (not installed as a package)")
|
|
39
39
|
return 0
|
|
40
40
|
|
|
41
41
|
|
|
@@ -109,15 +109,15 @@ def check_update_command(args: argparse.Namespace) -> int:
|
|
|
109
109
|
|
|
110
110
|
def _cli_update_commands(manager: str) -> list[list[str]]:
|
|
111
111
|
if manager == "uv":
|
|
112
|
-
return [["uv", "tool", "upgrade", "minder"]]
|
|
112
|
+
return [["uv", "tool", "upgrade", "minder-cli"]]
|
|
113
113
|
if manager == "pipx":
|
|
114
|
-
return [["pipx", "upgrade", "minder"]]
|
|
114
|
+
return [["pipx", "upgrade", "minder-cli"]]
|
|
115
115
|
if manager == "pip":
|
|
116
|
-
return [[sys.executable, "-m", "pip", "install", "--upgrade", "minder"]]
|
|
116
|
+
return [[sys.executable, "-m", "pip", "install", "--upgrade", "minder-cli"]]
|
|
117
117
|
return [
|
|
118
|
-
["uv", "tool", "upgrade", "minder"],
|
|
119
|
-
["pipx", "upgrade", "minder"],
|
|
120
|
-
[sys.executable, "-m", "pip", "install", "--upgrade", "minder"],
|
|
118
|
+
["uv", "tool", "upgrade", "minder-cli"],
|
|
119
|
+
["pipx", "upgrade", "minder-cli"],
|
|
120
|
+
[sys.executable, "-m", "pip", "install", "--upgrade", "minder-cli"],
|
|
121
121
|
]
|
|
122
122
|
|
|
123
123
|
|
|
@@ -6,11 +6,12 @@ from importlib.metadata import (
|
|
|
6
6
|
version as package_version,
|
|
7
7
|
)
|
|
8
8
|
|
|
9
|
+
from pathlib import Path
|
|
9
10
|
import httpx
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
12
13
|
|
|
13
|
-
_PYPI_JSON_URL = "https://pypi.org/pypi/minder/json"
|
|
14
|
+
_PYPI_JSON_URL = "https://pypi.org/pypi/minder-cli/json"
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def parse_version(raw_version: str) -> tuple[int, ...]:
|
|
@@ -26,8 +27,20 @@ def parse_version(raw_version: str) -> tuple[int, ...]:
|
|
|
26
27
|
|
|
27
28
|
def installed_package_version() -> str | None:
|
|
28
29
|
try:
|
|
29
|
-
return package_version("minder")
|
|
30
|
+
return package_version("minder-cli")
|
|
30
31
|
except PackageNotFoundError:
|
|
32
|
+
# Fallback for development mode: try to read from pyproject.toml
|
|
33
|
+
try:
|
|
34
|
+
# Look for pyproject.toml in the repo root (5 levels up from this file)
|
|
35
|
+
pyproject_path = Path(__file__).parents[5] / "pyproject.toml"
|
|
36
|
+
if pyproject_path.exists():
|
|
37
|
+
content = pyproject_path.read_text()
|
|
38
|
+
import re
|
|
39
|
+
match = re.search(r'^version\s*=\s*["\']([^"\']+)["\']', content, re.MULTILINE)
|
|
40
|
+
if match:
|
|
41
|
+
return match.group(1) + "-dev"
|
|
42
|
+
except Exception:
|
|
43
|
+
pass
|
|
31
44
|
return None
|
|
32
45
|
|
|
33
46
|
|
|
@@ -132,6 +132,7 @@ class RepoScanner:
|
|
|
132
132
|
self._git_metadata_cache: dict[str, dict[str, Any]] = {}
|
|
133
133
|
self._git_line_commit_cache: dict[tuple[str, int], dict[str, str] | None] = {}
|
|
134
134
|
self._git_commit_detail_cache: dict[str, dict[str, str]] = {}
|
|
135
|
+
self._git_file_blame_cache: dict[str, dict[int, str]] = {}
|
|
135
136
|
self._git_enabled = True
|
|
136
137
|
|
|
137
138
|
def _run_git(
|
|
@@ -280,6 +281,7 @@ class RepoScanner:
|
|
|
280
281
|
builder._git_metadata_cache = {}
|
|
281
282
|
builder._git_line_commit_cache = {}
|
|
282
283
|
builder._git_commit_detail_cache = {}
|
|
284
|
+
builder._git_file_blame_cache = {}
|
|
283
285
|
builder._git_enabled = True
|
|
284
286
|
|
|
285
287
|
service_dirs = builder._discover_service_boundaries()
|
|
@@ -374,24 +376,21 @@ class RepoScanner:
|
|
|
374
376
|
}
|
|
375
377
|
|
|
376
378
|
def _discover_service_boundaries(self) -> list[Path]:
|
|
377
|
-
service_dirs:
|
|
378
|
-
for
|
|
379
|
-
for
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
service_dirs.append(svc_dir)
|
|
385
|
-
return sorted(service_dirs, key=lambda path: len(path.parts), reverse=True)
|
|
379
|
+
service_dirs: set[Path] = set()
|
|
380
|
+
for path in self._root.rglob("*"):
|
|
381
|
+
if any(part.startswith(".") for part in path.parts):
|
|
382
|
+
continue
|
|
383
|
+
if path.is_file() and path.name in _SERVICE_MARKERS:
|
|
384
|
+
service_dirs.add(path.parent)
|
|
385
|
+
return sorted(list(service_dirs), key=lambda path: len(path.parts), reverse=True)
|
|
386
386
|
|
|
387
387
|
def _discover_source_files(self) -> list[Path]:
|
|
388
388
|
files: list[Path] = []
|
|
389
|
-
for
|
|
390
|
-
for
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
files.append(path)
|
|
389
|
+
for path in self._root.rglob("*"):
|
|
390
|
+
if any(part.startswith(".") or part == "__pycache__" for part in path.parts):
|
|
391
|
+
continue
|
|
392
|
+
if path.is_file() and path.suffix.lower() in _SOURCE_SUFFIXES:
|
|
393
|
+
files.append(path)
|
|
395
394
|
return sorted(set(files))
|
|
396
395
|
|
|
397
396
|
def _resolve_source_files(self, changed_files: list[str] | None) -> list[Path]:
|
|
@@ -579,34 +578,32 @@ class RepoScanner:
|
|
|
579
578
|
return commits
|
|
580
579
|
|
|
581
580
|
def _git_line_commit(self, rel_path: str, line_number: int) -> dict[str, str] | None:
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
581
|
+
if rel_path not in self._git_file_blame_cache:
|
|
582
|
+
result = self._run_git(["blame", "--line-porcelain", "--", rel_path], check=False)
|
|
583
|
+
if result.returncode != 0:
|
|
584
|
+
self._git_file_blame_cache[rel_path] = {}
|
|
585
|
+
else:
|
|
586
|
+
blame_data: dict[int, str] = {}
|
|
587
|
+
current_sha = None
|
|
588
|
+
for line in result.stdout.splitlines():
|
|
589
|
+
if not line:
|
|
590
|
+
continue
|
|
591
|
+
if current_sha is None:
|
|
592
|
+
current_sha = line.split(" ", 1)[0]
|
|
593
|
+
elif line.startswith("\t"):
|
|
594
|
+
# This line indicates the end of a porcelain block
|
|
595
|
+
current_sha = None
|
|
596
|
+
elif line.startswith("result-line "):
|
|
597
|
+
target_line = int(line.split(" ")[1])
|
|
598
|
+
if current_sha and set(current_sha) != {"0"}:
|
|
599
|
+
blame_data[target_line] = current_sha
|
|
600
|
+
self._git_file_blame_cache[rel_path] = blame_data
|
|
601
|
+
|
|
602
|
+
sha = self._git_file_blame_cache.get(rel_path, {}).get(line_number)
|
|
603
|
+
if not sha:
|
|
605
604
|
return None
|
|
606
605
|
|
|
607
|
-
|
|
608
|
-
self._git_line_commit_cache[cache_key] = details
|
|
609
|
-
return details
|
|
606
|
+
return self._git_commit_details(sha)
|
|
610
607
|
|
|
611
608
|
def _git_commit_details(self, sha: str) -> dict[str, str]:
|
|
612
609
|
cached = self._git_commit_detail_cache.get(sha)
|
|
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
|
|
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
|