mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
106 lines
3.0 KiB
Python
106 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Get git diff in a single git file for the closest git repo in the file system
|
|
NOTE: Since this is run as a script, there should be no imports from project files!
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
MAX_FILE_SIZE_FOR_GIT_DIFF = 1024 * 1024 # 1 Mb
|
|
|
|
|
|
def get_closest_git_repo(path: Path) -> Path | None:
|
|
while True:
|
|
path = path.parent
|
|
git_path = Path(path, '.git')
|
|
if git_path.is_dir():
|
|
return path
|
|
if path.parent == path:
|
|
return None
|
|
|
|
|
|
def run(cmd: str, cwd: str) -> str:
|
|
result = subprocess.run(
|
|
args=cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
|
|
)
|
|
byte_content = result.stderr or result.stdout or b''
|
|
|
|
if result.returncode != 0:
|
|
raise RuntimeError(
|
|
f'error_running_cmd:{result.returncode}:{byte_content.decode()}'
|
|
)
|
|
return byte_content.decode().strip()
|
|
|
|
|
|
def get_valid_ref(repo_dir: str) -> str | None:
|
|
refs = []
|
|
try:
|
|
current_branch = run('git --no-pager rev-parse --abbrev-ref HEAD', repo_dir)
|
|
refs.append(f'origin/{current_branch}')
|
|
except RuntimeError:
|
|
pass
|
|
|
|
try:
|
|
default_branch = (
|
|
run('git --no-pager remote show origin | grep "HEAD branch"', repo_dir)
|
|
.split()[-1]
|
|
.strip()
|
|
)
|
|
ref_non_default_branch = f'$(git --no-pager merge-base HEAD "$(git --no-pager rev-parse --abbrev-ref origin/{default_branch})")'
|
|
ref_default_branch = f'origin/{default_branch}'
|
|
refs.append(ref_non_default_branch)
|
|
refs.append(ref_default_branch)
|
|
except RuntimeError:
|
|
pass
|
|
|
|
# compares with empty tree
|
|
ref_new_repo = (
|
|
'$(git --no-pager rev-parse --verify 4b825dc642cb6eb9a060e54bf8d69288fbee4904)'
|
|
)
|
|
refs.append(ref_new_repo)
|
|
|
|
# Find a ref that exists...
|
|
for ref in refs:
|
|
try:
|
|
result = run(f'git --no-pager rev-parse --verify {ref}', repo_dir)
|
|
return result
|
|
except RuntimeError:
|
|
# invalid ref - try next
|
|
continue
|
|
|
|
return None
|
|
|
|
|
|
def get_git_diff(relative_file_path: str) -> dict[str, str]:
|
|
path = Path(os.getcwd(), relative_file_path).resolve()
|
|
if os.path.getsize(path) > MAX_FILE_SIZE_FOR_GIT_DIFF:
|
|
raise ValueError('file_to_large')
|
|
closest_git_repo = get_closest_git_repo(path)
|
|
if not closest_git_repo:
|
|
raise ValueError('no_repository')
|
|
current_rev = get_valid_ref(str(closest_git_repo))
|
|
try:
|
|
original = run(
|
|
f'git show "{current_rev}:{path.relative_to(closest_git_repo)}"',
|
|
str(closest_git_repo),
|
|
)
|
|
except RuntimeError:
|
|
original = ''
|
|
try:
|
|
with open(path, 'r') as f:
|
|
modified = '\n'.join(f.read().splitlines())
|
|
except FileNotFoundError:
|
|
modified = ''
|
|
return {
|
|
'modified': modified,
|
|
'original': original,
|
|
}
|
|
|
|
|
|
if __name__ == '__main__':
|
|
diff = get_git_diff(sys.argv[-1])
|
|
print(json.dumps(diff))
|