from typing import Any from gitea.client import GiteaClient class FileTools: """Tools for Gitea file/content operations.""" def __init__(self, client: GiteaClient) -> None: self._client = client def _paginate_lines( self, content: str, offset: int, limit: int, ) -> str: """Return lines[offset-1 : offset-1+limit] with a paging footer if truncated. Uses the same 1-indexed convention as CodingTools.read_file. """ lines: list[str] = content.splitlines() total: int = len(lines) start: int = offset - 1 # convert to 0-indexed page: list[str] = lines[start : start + limit] formatted: list[str] = [ f"{start + i + 1}: {line}" for i, line in enumerate(page) ] result: str = "\n".join(formatted) end_line: int = start + len(page) if end_line < total: next_offset: int = end_line + 1 result += ( f"\n\n[{total} lines total — showing lines {offset}–{end_line}. " f"Re-call with offset={next_offset} to read more.]" ) return result def get_file_content( self, owner: str, repo: str, path: str, offset: int = 1, limit: int = 250, ) -> str: """Get the content of a file from a Gitea repository with line paging. Args: offset: 1-indexed line to start from (default 1). limit: Maximum number of lines to return (default 250). """ try: content = self._client.files.get_file_content(owner, repo, path) raw: str = "\n".join(content) if isinstance(content, list) else content return self._paginate_lines(raw, offset, limit) except Exception as e: return f"Error getting file content: {str(e)}" def get_file_content_with_ref( self, owner: str, repo: str, path: str, ref: str = "master", offset: int = 1, limit: int = 250, ) -> str: """Get file content at a specific git ref with line paging. Args: ref: Branch, tag, or commit SHA (default 'master'). offset: 1-indexed line to start from (default 1). limit: Maximum number of lines to return (default 250). """ try: content = self._client.files.get_file_content(owner, repo, path, ref) raw: str = "\n".join(content) if isinstance(content, list) else content return self._paginate_lines(raw, offset, limit) except Exception as e: return f"Error getting file content: {str(e)}" def commit_file( self, owner: str, repo: str, path: str, message: str, content: str, branch: str ) -> str: try: self._client.files.update_file(owner, repo, path, message, content, branch) return f"File '{path}' committed successfully to {owner}/{repo}." except Exception as e: return f"Error committing file: {str(e)}" def update_file( self, owner: str, repo: str, path: str, message: str, content: str, branch: str ) -> str: try: self._client.files.update_file(owner, repo, path, message, content, branch) return f"File '{path}' updated in {owner}/{repo}." except Exception as e: return f"Error updating file: {str(e)}"