Skip to content

Commit da1969a

Browse files
authored
Add Git support (#72)
1 parent f7b3904 commit da1969a

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

src/cwhy/functions.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import openai
88

99
from . import clangd_lsp_integration
10+
from . import git_integration
1011

1112

1213
class Functions:
@@ -23,6 +24,18 @@ def as_tools(self) -> list[openai.types.responses.FunctionToolParam]:
2324

2425
if clangd_lsp_integration.is_available():
2526
fns.append(self.find_definition)
27+
else:
28+
print(
29+
"[WARNING] clangd is not available. The 'find_definition' function will not be made available."
30+
)
31+
32+
if git_integration.is_available():
33+
fns.append(self.git_status)
34+
fns.append(self.git_diff)
35+
else:
36+
print(
37+
"[WARNING] `git status` is not available. The associated git functions will not be made available."
38+
)
2639

2740
for f in fns:
2841
assert f.__doc__
@@ -55,6 +68,12 @@ def dispatch(
5568
return self.find_definition(
5669
arguments["filename"], arguments["line_number"], arguments["symbol"]
5770
)
71+
elif function_call.name == "git_status":
72+
return self.git_status()
73+
elif function_call.name == "git_diff":
74+
return self.git_diff(arguments["filename"])
75+
else:
76+
print(f"[ERROR] Unknown function: {function_call.name}")
5877
except Exception as e:
5978
print(e)
6079
return None
@@ -121,7 +140,7 @@ def list_directory(self, path: str) -> str:
121140
result = "\n".join(entries)
122141
print(result)
123142
return result
124-
143+
125144
def find_definition(self, filename: str, line_number: int, symbol: str) -> str:
126145
"""
127146
{
@@ -148,6 +167,47 @@ def find_definition(self, filename: str, line_number: int, symbol: str) -> str:
148167
}
149168
}
150169
"""
151-
result = clangd_lsp_integration.definition_plus_heuristics(filename, line_number, symbol)
170+
result = clangd_lsp_integration.definition_plus_heuristics(
171+
filename, line_number, symbol
172+
)
152173
print(result)
153174
return result
175+
176+
def git_status(self) -> str:
177+
"""
178+
{
179+
"description": "Returns the git status (--porcelain) of the current repository.",
180+
"strict": true,
181+
"parameters": {
182+
"type": "object",
183+
"properties": {},
184+
"required": [],
185+
"additionalProperties": false
186+
}
187+
}
188+
"""
189+
status = git_integration.get_git_status_porcelain()
190+
print(status)
191+
return status
192+
193+
def git_diff(self, filename: str) -> str:
194+
"""
195+
{
196+
"description": "Returns the diff since the last commit of the given file.",
197+
"strict": true,
198+
"parameters": {
199+
"type": "object",
200+
"properties": {
201+
"filename": {
202+
"type": "string",
203+
"description": "The filename path to get the git diff for (relative to the current directory)."
204+
}
205+
},
206+
"required": ["filename"],
207+
"additionalProperties": false
208+
}
209+
}
210+
"""
211+
diff = git_integration.get_git_diff(filename)
212+
print(diff)
213+
return diff

src/cwhy/git_integration.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import subprocess
2+
3+
4+
def is_available() -> bool:
5+
try:
6+
return (
7+
subprocess.run(
8+
["git", "status"],
9+
stdout=subprocess.DEVNULL,
10+
stderr=subprocess.DEVNULL,
11+
).returncode
12+
== 0
13+
)
14+
except FileNotFoundError:
15+
return False
16+
17+
18+
def get_git_status_porcelain() -> str:
19+
return subprocess.run(
20+
["git", "status", "--porcelain"],
21+
stdout=subprocess.PIPE,
22+
stderr=subprocess.DEVNULL,
23+
text=True,
24+
).stdout.strip()
25+
26+
27+
def get_git_diff(filename: str) -> str:
28+
return subprocess.run(
29+
["git", "diff", filename],
30+
stdout=subprocess.PIPE,
31+
stderr=subprocess.DEVNULL,
32+
text=True,
33+
).stdout.strip()

0 commit comments

Comments
 (0)