гих хук и сохранение изменений в контексте стори
This commit is contained in:
Binary file not shown.
@@ -10,6 +10,8 @@ class TextChunk:
|
||||
index: int
|
||||
text: str
|
||||
hash: str
|
||||
start_line: int | None = None
|
||||
end_line: int | None = None
|
||||
|
||||
|
||||
def _hash_text(text: str) -> str:
|
||||
@@ -27,7 +29,15 @@ def chunk_text(text: str, chunk_size: int, overlap: int) -> list[TextChunk]:
|
||||
while start < len(tokens):
|
||||
end = min(start + chunk_size, len(tokens))
|
||||
chunk_text_value = " ".join(tokens[start:end])
|
||||
chunks.append(TextChunk(index=index, text=chunk_text_value, hash=_hash_text(chunk_text_value)))
|
||||
chunks.append(
|
||||
TextChunk(
|
||||
index=index,
|
||||
text=chunk_text_value,
|
||||
hash=_hash_text(chunk_text_value),
|
||||
start_line=None,
|
||||
end_line=None,
|
||||
)
|
||||
)
|
||||
index += 1
|
||||
if end == len(tokens):
|
||||
break
|
||||
@@ -40,3 +50,34 @@ def iter_chunks(
|
||||
) -> Iterator[list[TextChunk]]:
|
||||
for text in texts:
|
||||
yield chunk_text(text, chunk_size, overlap)
|
||||
|
||||
|
||||
def chunk_text_by_lines(
|
||||
text: str, max_lines: int, overlap_lines: int
|
||||
) -> list[TextChunk]:
|
||||
"""Chunk by consecutive lines; each chunk has start_line/end_line (1-based)."""
|
||||
lines = text.splitlines()
|
||||
if not lines:
|
||||
return []
|
||||
|
||||
chunks: list[TextChunk] = []
|
||||
index = 0
|
||||
start = 0
|
||||
while start < len(lines):
|
||||
end = min(start + max_lines, len(lines))
|
||||
chunk_lines = lines[start:end]
|
||||
chunk_text_value = "\n".join(chunk_lines)
|
||||
chunks.append(
|
||||
TextChunk(
|
||||
index=index,
|
||||
text=chunk_text_value,
|
||||
hash=_hash_text(chunk_text_value),
|
||||
start_line=start + 1,
|
||||
end_line=end,
|
||||
)
|
||||
)
|
||||
index += 1
|
||||
if end == len(lines):
|
||||
break
|
||||
start = max(end - overlap_lines, 0)
|
||||
return chunks
|
||||
|
||||
@@ -40,3 +40,53 @@ def filter_existing(paths: Iterable[Path]) -> list[Path]:
|
||||
|
||||
def filter_removed(paths: Iterable[Path]) -> list[Path]:
|
||||
return [path for path in paths if not path.exists()]
|
||||
|
||||
|
||||
def get_merge_base(
|
||||
repo_path: str, ref1: str, ref2: str = "HEAD"
|
||||
) -> str | None:
|
||||
"""Return merge-base commit of ref1 and ref2 (start of story range). None on error."""
|
||||
args = [
|
||||
"git",
|
||||
"-C",
|
||||
repo_path,
|
||||
"merge-base",
|
||||
ref1,
|
||||
ref2,
|
||||
]
|
||||
try:
|
||||
result = subprocess.run(
|
||||
args,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result.stdout.strip() or None
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
|
||||
def read_file_at_ref(
|
||||
repo_path: str, path: Path, ref: str
|
||||
) -> str | None:
|
||||
"""Read file content at a git ref. Returns None if path is missing at ref."""
|
||||
repo = Path(repo_path)
|
||||
rel = path.relative_to(repo) if path.is_absolute() else path
|
||||
rel_str = rel.as_posix()
|
||||
args = [
|
||||
"git",
|
||||
"-C",
|
||||
repo_path,
|
||||
"show",
|
||||
f"{ref}:{rel_str}",
|
||||
]
|
||||
try:
|
||||
result = subprocess.run(
|
||||
args,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result.stdout
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user