code-context-control 2.40.0__py3-none-any.whl → 2.41.0__py3-none-any.whl
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.
- cli/c3.py +1 -1
- cli/tools/shell.py +71 -1
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/METADATA +1 -1
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/RECORD +8 -8
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/WHEEL +0 -0
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/entry_points.txt +0 -0
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/licenses/LICENSE +0 -0
- {code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/top_level.txt +0 -0
cli/c3.py
CHANGED
cli/tools/shell.py
CHANGED
|
@@ -4,12 +4,21 @@ Wraps subprocess.Popen with the Windows-safe pattern from
|
|
|
4
4
|
services/edit_ledger.py::_git_combined (Popen + taskkill /F /T + stdin=DEVNULL).
|
|
5
5
|
Auto-filters long stdout via handle_filter, auto-logs git mutations
|
|
6
6
|
to the edit ledger, and accounts stdout tokens against session budget.
|
|
7
|
+
|
|
8
|
+
Shell selection: on Windows, commands are run through Git Bash (bash.exe) when
|
|
9
|
+
it is available, so c3_shell speaks the same POSIX dialect as the native Bash
|
|
10
|
+
tool (forward-slash paths, single quotes, `$VAR`, ls/grep/cat, heredocs). This
|
|
11
|
+
avoids the cmd.exe/POSIX mismatch that forced callers to fall back to native
|
|
12
|
+
Bash for bash-flavored commands. Set C3_SHELL_BASH=0 to force cmd.exe, or point
|
|
13
|
+
C3_SHELL_BASH at a specific bash.exe to override discovery. POSIX platforms are
|
|
14
|
+
unchanged (shell=True → /bin/sh).
|
|
7
15
|
"""
|
|
8
16
|
from __future__ import annotations
|
|
9
17
|
|
|
10
18
|
import asyncio
|
|
11
19
|
import os
|
|
12
20
|
import re
|
|
21
|
+
import shutil
|
|
13
22
|
import subprocess
|
|
14
23
|
import sys
|
|
15
24
|
import time
|
|
@@ -59,6 +68,58 @@ _MAX_TIMEOUT = 600
|
|
|
59
68
|
_FILTER_THRESHOLD_LINES = 30
|
|
60
69
|
|
|
61
70
|
|
|
71
|
+
# Cache for discovered Git Bash path: [] = uncomputed, [None]/[path] = computed.
|
|
72
|
+
_bash_cache: list = []
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _discover_git_bash() -> str | None:
|
|
76
|
+
"""Locate a Git-for-Windows bash.exe, never WSL/System32 bash.
|
|
77
|
+
|
|
78
|
+
WSL's bash runs in a Linux subsystem with /mnt/c paths, which would break
|
|
79
|
+
the Windows `cwd` semantics every caller relies on — so it is rejected.
|
|
80
|
+
"""
|
|
81
|
+
candidates: list[str] = []
|
|
82
|
+
for base_env in ("ProgramW6432", "ProgramFiles", "ProgramFiles(x86)"):
|
|
83
|
+
base = os.environ.get(base_env)
|
|
84
|
+
if base:
|
|
85
|
+
candidates.append(os.path.join(base, "Git", "bin", "bash.exe"))
|
|
86
|
+
candidates.append(os.path.join(base, "Git", "usr", "bin", "bash.exe"))
|
|
87
|
+
candidates.append(r"C:\Program Files\Git\bin\bash.exe")
|
|
88
|
+
candidates.append(r"C:\Program Files\Git\usr\bin\bash.exe")
|
|
89
|
+
for path in candidates:
|
|
90
|
+
if os.path.isfile(path):
|
|
91
|
+
return path
|
|
92
|
+
# Last resort: PATH lookup, but reject WSL/Store bash (System32/WindowsApps).
|
|
93
|
+
found = shutil.which("bash")
|
|
94
|
+
if found:
|
|
95
|
+
low = found.lower()
|
|
96
|
+
if "system32" not in low and "windowsapps" not in low:
|
|
97
|
+
return found
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _select_bash() -> str | None:
|
|
102
|
+
"""Return the bash.exe to run commands through on Windows, else None.
|
|
103
|
+
|
|
104
|
+
None means "use the platform default shell" (cmd.exe on Windows via
|
|
105
|
+
shell=True, /bin/sh on POSIX). Honors the C3_SHELL_BASH override:
|
|
106
|
+
'0'/'cmd' forces the platform default; an existing file path forces that
|
|
107
|
+
bash. Discovery is cached after the first call.
|
|
108
|
+
"""
|
|
109
|
+
if sys.platform != "win32":
|
|
110
|
+
return None
|
|
111
|
+
override = os.environ.get("C3_SHELL_BASH")
|
|
112
|
+
if override is not None:
|
|
113
|
+
if override.strip().lower() in ("0", "", "cmd", "false", "off"):
|
|
114
|
+
return None
|
|
115
|
+
if os.path.isfile(override):
|
|
116
|
+
return override
|
|
117
|
+
# Unrecognized override → fall through to discovery.
|
|
118
|
+
if not _bash_cache:
|
|
119
|
+
_bash_cache.append(_discover_git_bash())
|
|
120
|
+
return _bash_cache[0]
|
|
121
|
+
|
|
122
|
+
|
|
62
123
|
def _popen_kwargs() -> dict:
|
|
63
124
|
# Force UTF-8 in child processes so Unicode output (→, box-drawing, emoji)
|
|
64
125
|
# doesn't crash on Windows' legacy cp1252 console encoding. setdefault so an
|
|
@@ -89,8 +150,17 @@ def _kill_tree(proc: subprocess.Popen) -> None:
|
|
|
89
150
|
def _run_sync(cmd: str, cwd: str, timeout: int) -> dict:
|
|
90
151
|
"""Blocking subprocess run with hard kill on timeout. Returns structured dict."""
|
|
91
152
|
start = time.time()
|
|
153
|
+
bash = _select_bash()
|
|
154
|
+
if bash:
|
|
155
|
+
# POSIX dialect via Git Bash — matches the native Bash tool.
|
|
156
|
+
popen_target: object = [bash, "-c", cmd]
|
|
157
|
+
use_shell = False
|
|
158
|
+
else:
|
|
159
|
+
# Platform default: cmd.exe on Windows, /bin/sh on POSIX.
|
|
160
|
+
popen_target = cmd
|
|
161
|
+
use_shell = True
|
|
92
162
|
proc = subprocess.Popen(
|
|
93
|
-
|
|
163
|
+
popen_target, shell=use_shell, cwd=cwd,
|
|
94
164
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
95
165
|
text=True, encoding="utf-8", errors="replace",
|
|
96
166
|
**_popen_kwargs(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.41.0
|
|
4
4
|
Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cli/__init__.py,sha256=ec66drCZGNMRU4V6ov0zVhYZph1us12Vn8OvG_LJyRY,22
|
|
2
2
|
cli/_hook_utils.py,sha256=rzW3u3Yrlvh73s_UZrQojkwGnKnS4yrPlbt4xouqQFM,5139
|
|
3
|
-
cli/c3.py,sha256=
|
|
3
|
+
cli/c3.py,sha256=Gbnou4BbpWrMR1TZdIlGcr3EeTpifBev2akFGFsgC8E,300436
|
|
4
4
|
cli/docs.html,sha256=JgtBFUuUkvmYowPREYiGhhcRbB5e2UjkRc00MIF0hsU,143653
|
|
5
5
|
cli/edits.html,sha256=UjAhoCmBmQ89cklGvJqzC6eyNP2tc8H6T-e01DVkLvE,43418
|
|
6
6
|
cli/hook_auto_snapshot.py,sha256=amtliVDzKUQr6KBR0pdBA8vXghAV-gKr19jBaJVnP_w,5006
|
|
@@ -47,7 +47,7 @@ cli/tools/project.py,sha256=PKHLGRFZdwBBEgryyV440mybTeQMqnlLgHdfXDnPahw,11868
|
|
|
47
47
|
cli/tools/read.py,sha256=sl-dXlfFd7zCMOz-foy5lWk0j2EF_GWfJp8YZ4GXvqo,11754
|
|
48
48
|
cli/tools/search.py,sha256=qB8C3w8yuu59aepvnuJNlzbsirtSEZA8zz4neKlE7Xs,13246
|
|
49
49
|
cli/tools/session.py,sha256=LIZbmEhNdh6rAsT6Dbpb21UY8xF9oubvpjGwfnXxQK4,4573
|
|
50
|
-
cli/tools/shell.py,sha256=
|
|
50
|
+
cli/tools/shell.py,sha256=vGsvzQLISo-daKF40ZhRJXS5lDA6OV1t9RWoyqdlpt4,12617
|
|
51
51
|
cli/tools/status.py,sha256=yCHXskXgKzaDhJT6vHYlp3ZU5j89vhVYzf5dQOAR9yQ,12625
|
|
52
52
|
cli/tools/validate.py,sha256=3GaYP9Kntep2SqKiAChUQxySWp1B-X3EuawUtIUQR40,12891
|
|
53
53
|
cli/ui/api.js,sha256=wI9-lxGitIgZ5R6lqi1PVc2edD0b3TsYwMUGgcNWgfU,1342
|
|
@@ -64,7 +64,7 @@ cli/ui/components/memory.js,sha256=v5IsHTxLHpXX4xCsUaZ_UPprZEabdgP4jiWc298iV2U,2
|
|
|
64
64
|
cli/ui/components/sessions.js,sha256=FIKtil76B8tCkAmcFV7hlj6GQ_DCJK2jCzvEmdK7NBE,30837
|
|
65
65
|
cli/ui/components/settings.js,sha256=8LVTV2TQl9tcRXhXbtBEJOCBdiyk-x2QASoVYZUAuEA,71442
|
|
66
66
|
cli/ui/components/sidebar.js,sha256=cAY_jwYB-o1X_wWn__VXlG4IegVObuE3NmVsuFWqxtg,7417
|
|
67
|
-
code_context_control-2.
|
|
67
|
+
code_context_control-2.41.0.dist-info/licenses/LICENSE,sha256=l8Kh5QCNWNvR6kIt8L0BUZvc2LAFiHv2c-FnsGnUZf4,11301
|
|
68
68
|
core/__init__.py,sha256=TSDCEcM4V7gcZVM3w2ykJaqEUch4Dkon-rivV17T73s,2501
|
|
69
69
|
core/config.py,sha256=tF0BKg2O_77Q9y2guyqdSF3INxMrKGlqUeGbTxmHmhI,14245
|
|
70
70
|
core/ide.py,sha256=9LzsDVK2LL8RVpL40l6oNGiasZ3D8OCU_9i9A0gJKBo,6876
|
|
@@ -165,8 +165,8 @@ tui/screens/search_view.py,sha256=MMHjVdlk3HZSuDBSvq8IGrqv_Mh5Us6YqXQ80bcWSMk,19
|
|
|
165
165
|
tui/screens/session_view.py,sha256=eZ1eDwHTvPOck1wCCviixtOaCxIkBT_95ytNNNriGNA,5991
|
|
166
166
|
tui/screens/stats.py,sha256=p81PjzdaIv7hllb8f45-rlVe4lJZwSdIMqu7e86_u5s,6223
|
|
167
167
|
tui/screens/ui_view.py,sha256=1QJCgLh2YfgWIpvzRG1KOGXYEaOYX6ojN61Azjf2oX0,2125
|
|
168
|
-
code_context_control-2.
|
|
169
|
-
code_context_control-2.
|
|
170
|
-
code_context_control-2.
|
|
171
|
-
code_context_control-2.
|
|
172
|
-
code_context_control-2.
|
|
168
|
+
code_context_control-2.41.0.dist-info/METADATA,sha256=xYB3b_utLQa_yHV_8btp9ZJxKj4qS_9T0LtbImi4_Do,22274
|
|
169
|
+
code_context_control-2.41.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
170
|
+
code_context_control-2.41.0.dist-info/entry_points.txt,sha256=7kX_WUsDCF2hbXzvbNyscyaBb9AeA-DJY5v_5hN0DlU,93
|
|
171
|
+
code_context_control-2.41.0.dist-info/top_level.txt,sha256=wRt41zBybVF3qAiNXHz9BURbkKvUvfhmWWtKMhaw6eE,29
|
|
172
|
+
code_context_control-2.41.0.dist-info/RECORD,,
|
|
File without changes
|
{code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{code_context_control-2.40.0.dist-info → code_context_control-2.41.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|