#!/usr/bin/env python3 """ Final solution: Commit to Gitea repository using Gitea REST API This bypasses git.exe issues and works directly with the Gitea server. """ import os import sys import base64 import requests import json from datetime import datetime from pathlib import Path # Gitea configuration GITEA_URL = "https://git.mtrcompute.com" USERNAME = "jleu3482" PASSWORD = "jleu1212" REPO_OWNER = "jleu3482" REPO_NAME = "railseek6" class GiteaCommiter: """Commit files to Gitea using REST API""" def __init__(self): self.session = requests.Session() self.token = None self.repo_url = f"{GITEA_URL}/api/v1/repos/{REPO_OWNER}/{REPO_NAME}" def authenticate(self): """Authenticate with Gitea and get token""" print("Authenticating with Gitea...") # Try to get existing tokens first tokens_url = f"{GITEA_URL}/api/v1/users/{USERNAME}/tokens" try: response = self.session.get( tokens_url, auth=(USERNAME, PASSWORD) ) if response.status_code == 200: tokens = response.json() for token in tokens: if "auto-commit" in token.get("name", ""): self.token = token["sha1"] print(f"✓ Using existing token: {token['name']}") return True except: pass # Create new token token_name = f"auto-commit-{datetime.now().strftime('%Y%m%d')}" token_data = { "name": token_name, "scopes": ["all"] } try: response = self.session.post( tokens_url, json=token_data, auth=(USERNAME, PASSWORD) ) if response.status_code == 201: self.token = response.json()["sha1"] print(f"✓ Created new token: {token_name}") return True else: print(f"❌ Failed to create token: {response.status_code}") print(f"Response: {response.text}") return False except Exception as e: print(f"❌ Error creating token: {e}") return False def get_file_content(self, filepath): """Read file and encode as base64""" try: with open(filepath, 'rb') as f: content = f.read() # Check if file is binary if b'\x00' in content[:1024]: print(f"⚠ Skipping binary file: {filepath}") return None return base64.b64encode(content).decode('utf-8') except Exception as e: print(f"❌ Error reading {filepath}: {e}") return None def get_repo_files(self): """Get list of files already in repository""" try: response = self.session.get( f"{self.repo_url}/contents", headers={"Authorization": f"token {self.token}"} ) if response.status_code == 200: return {item["path"]: item["sha"] for item in response.json()} else: return {} except: return {} def commit_file(self, filepath, rel_path, commit_message): """Commit a single file to repository""" content_b64 = self.get_file_content(filepath) if not content_b64: return False # Check if file exists in repo existing_files = self.get_repo_files() file_data = { "message": commit_message, "content": content_b64, "branch": "main" } if rel_path in existing_files: file_data["sha"] = existing_files[rel_path] try: response = self.session.put( f"{self.repo_url}/contents/{rel_path}", json=file_data, headers={"Authorization": f"token {self.token}"} ) if response.status_code in [201, 200]: print(f"✓ Committed: {rel_path}") return True else: print(f"❌ Failed to commit {rel_path}: {response.status_code}") print(f"Response: {response.text[:200]}") return False except Exception as e: print(f"❌ Error committing {rel_path}: {e}") return False def commit_directory(self, description, max_files=50): """Commit all files in current directory""" if not self.authenticate(): return False timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") commit_message = f"{description}\n\nAuto-commit at: {timestamp}" print(f"\nCommitting with message: {description}") print(f"Repository: {GITEA_URL}/{REPO_OWNER}/{REPO_NAME}") print() # Collect files to commit files_to_commit = [] for root, dirs, files in os.walk("."): # Skip hidden directories and .git dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for file in files: filepath = os.path.join(root, file) rel_path = os.path.relpath(filepath, ".") # Skip large files if os.path.getsize(filepath) > 5 * 1024 * 1024: # 5MB limit continue # Skip certain file types skip_extensions = ['.pyc', '.pyo', '.so', '.dll', '.exe', '.pdb'] if any(rel_path.endswith(ext) for ext in skip_extensions): continue files_to_commit.append((filepath, rel_path)) print(f"Found {len(files_to_commit)} files to commit") print("Committing files (this may take a moment)...") # Commit files (limit to max_files) successful = 0 for i, (filepath, rel_path) in enumerate(files_to_commit[:max_files]): print(f"[{i+1}/{min(len(files_to_commit), max_files)}] ", end="") if self.commit_file(filepath, rel_path, commit_message): successful += 1 print(f"\n✓ Successfully committed {successful} files") return successful > 0 def create_readme(self): """Create README.md if it doesn't exist""" readme_content = """# RailSeek6 - LightRAG Project This repository contains the RailSeek6 LightRAG project with GPU-accelerated OCR and document search capabilities. ## Features - Document upload and processing with OCR - GPU-accelerated image classification using OpenCLIP - Vector search with Qdrant - Web UI for document search and retrieval - Auto-commit functionality with Gitea integration ## Setup 1. Install dependencies: `pip install -r requirements.txt` 2. Start server: `python start_server_fixed.py` 3. Access Web UI: http://localhost:3015 ## Repository Information - Gitea URL: https://git.mtrcompute.com/jleu3482/railseek6 - Auto-commit: Enabled for major changes - Last commit: {timestamp} """ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") readme_content = readme_content.format(timestamp=timestamp) readme_b64 = base64.b64encode(readme_content.encode('utf-8')).decode('utf-8') commit_message = "Initial commit: RailSeek6 LightRAG project" file_data = { "message": commit_message, "content": readme_b64, "branch": "main" } try: response = self.session.put( f"{self.repo_url}/contents/README.md", json=file_data, headers={"Authorization": f"token {self.token}"} ) if response.status_code in [201, 200]: print("✓ Created README.md") return True else: return False except: return False def main(): """Main function""" if len(sys.argv) < 2: print("Usage: python final_gitea_commit.py \"Description of changes\"") print("Example: python final_gitea_commit.py \"Added document download endpoint\"") print("\nOptional arguments:") print(" --max-files N Limit to N files (default: 50)") print(" --create-readme Create README.md if missing") sys.exit(1) description = sys.argv[1] max_files = 50 create_readme = False # Parse arguments args = sys.argv[2:] i = 0 while i < len(args): if args[i] == "--max-files" and i + 1 < len(args): max_files = int(args[i + 1]) i += 2 elif args[i] == "--create-readme": create_readme = True i += 1 else: i += 1 print("=" * 60) print("GITEA API COMMIT - FINAL SOLUTION") print("=" * 60) print(f"Repository: {GITEA_URL}/{REPO_OWNER}/{REPO_NAME}") print(f"Description: {description}") print(f"Max files: {max_files}") print() commiter = GiteaCommiter() # Create README if requested if create_readme: if commiter.authenticate(): commiter.create_readme() # Commit directory success = commiter.commit_directory(description, max_files) print() print("=" * 60) print("COMMIT COMPLETE") print("=" * 60) if success: print(f"✅ Successfully committed to Gitea repository") print(f"📁 Repository: {GITEA_URL}/{REPO_OWNER}/{REPO_NAME}") print(f"📝 Commit: {description}") print(f"🕒 Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print() print("View your repository at:") print(f" https://git.mtrcompute.com/jleu3482/railseek6") else: print("❌ Failed to commit to repository") print("Check your credentials and network connection") print("=" * 60) if __name__ == "__main__": main()