Analysis: Git vs Go-Git comparison and recommendation
This commit is contained in:
262
auto_commit_gogit.py
Normal file
262
auto_commit_gogit.py
Normal file
@@ -0,0 +1,262 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Go-Git Auto-Commit Script for LightRAG project.
|
||||
Uses Gitea API directly instead of external Git.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import hashlib
|
||||
import base64
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
class GoGitAutoCommit:
|
||||
def __init__(self, gitea_url, username, password, repo_owner, repo_name):
|
||||
self.gitea_url = gitea_url.rstrip('/')
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.repo_owner = repo_owner
|
||||
self.repo_name = repo_name
|
||||
self.session = requests.Session()
|
||||
self.session.auth = (username, password)
|
||||
|
||||
def get_auth_token(self):
|
||||
"""Get or create an access token for API calls."""
|
||||
# Try to get existing tokens
|
||||
tokens_url = f"{self.gitea_url}/api/v1/users/{self.username}/tokens"
|
||||
response = self.session.get(tokens_url)
|
||||
|
||||
if response.status_code == 200:
|
||||
tokens = response.json()
|
||||
if tokens:
|
||||
return tokens[0]['sha1']
|
||||
|
||||
# Create new token
|
||||
token_data = {
|
||||
"name": f"auto-commit-{datetime.now().strftime('%Y%m%d')}",
|
||||
"scopes": ["write:repository", "read:repository"]
|
||||
}
|
||||
|
||||
response = self.session.post(tokens_url, json=token_data)
|
||||
if response.status_code == 201:
|
||||
return response.json()['sha1']
|
||||
else:
|
||||
raise Exception(f"Failed to create token: {response.text}")
|
||||
|
||||
def calculate_file_hash(self, file_path):
|
||||
"""Calculate SHA1 hash for file (Go-Git compatible)."""
|
||||
with open(file_path, 'rb') as f:
|
||||
content = f.read()
|
||||
sha1 = hashlib.sha1(content).hexdigest()
|
||||
return sha1, len(content)
|
||||
|
||||
def create_file_content(self, file_path, relative_path):
|
||||
"""Create file content entry for Gitea API."""
|
||||
sha1, size = self.calculate_file_hash(file_path)
|
||||
|
||||
with open(file_path, 'rb') as f:
|
||||
content = f.read()
|
||||
encoded = base64.b64encode(content).decode('utf-8')
|
||||
|
||||
return {
|
||||
"path": relative_path,
|
||||
"sha": sha1,
|
||||
"size": size,
|
||||
"content": encoded,
|
||||
"encoding": "base64"
|
||||
}
|
||||
|
||||
def get_repo_tree(self, ref="master"):
|
||||
"""Get current repository tree."""
|
||||
url = f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/git/trees/{ref}"
|
||||
response = self.session.get(url)
|
||||
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
# Repository might be empty
|
||||
return {"tree": [], "sha": None}
|
||||
|
||||
def find_changed_files(self, base_dir="."):
|
||||
"""Find changed files by comparing with current tree."""
|
||||
base_path = Path(base_dir)
|
||||
changed_files = []
|
||||
|
||||
# Get current tree
|
||||
current_tree = self.get_repo_tree()
|
||||
current_files = {item['path']: item['sha'] for item in current_tree.get('tree', [])}
|
||||
|
||||
# Walk through directory
|
||||
for file_path in base_path.rglob('*'):
|
||||
if file_path.is_file():
|
||||
# Skip .git directory and other ignored files
|
||||
if '.git' in str(file_path):
|
||||
continue
|
||||
|
||||
relative_path = str(file_path.relative_to(base_path))
|
||||
|
||||
# Calculate current hash
|
||||
current_sha1, _ = self.calculate_file_hash(file_path)
|
||||
|
||||
# Check if file is new or modified
|
||||
if relative_path not in current_files:
|
||||
changed_files.append(("added", relative_path, file_path))
|
||||
elif current_sha1 != current_files[relative_path]:
|
||||
changed_files.append(("modified", relative_path, file_path))
|
||||
|
||||
return changed_files
|
||||
|
||||
def create_commit(self, message, changed_files, base_dir="."):
|
||||
"""Create a commit using Gitea API."""
|
||||
# Get current commit reference
|
||||
ref_url = f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/git/refs/heads/master"
|
||||
response = self.session.get(ref_url)
|
||||
|
||||
if response.status_code == 404:
|
||||
# Branch doesn't exist yet (empty repo)
|
||||
parent_sha = None
|
||||
elif response.status_code == 200:
|
||||
parent_sha = response.json()['object']['sha']
|
||||
else:
|
||||
raise Exception(f"Failed to get ref: {response.text}")
|
||||
|
||||
# Create tree with changed files
|
||||
tree_items = []
|
||||
|
||||
for change_type, relative_path, file_path in changed_files:
|
||||
if change_type in ["added", "modified"]:
|
||||
file_content = self.create_file_content(file_path, relative_path)
|
||||
tree_items.append({
|
||||
"path": relative_path,
|
||||
"mode": "100644", # Regular file
|
||||
"type": "blob",
|
||||
"sha": file_content["sha"]
|
||||
})
|
||||
|
||||
# Create tree
|
||||
tree_data = {
|
||||
"base_tree": parent_sha,
|
||||
"tree": tree_items
|
||||
}
|
||||
|
||||
tree_url = f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/git/trees"
|
||||
response = self.session.post(tree_url, json=tree_data)
|
||||
|
||||
if response.status_code != 201:
|
||||
raise Exception(f"Failed to create tree: {response.text}")
|
||||
|
||||
tree_sha = response.json()['sha']
|
||||
|
||||
# Create commit
|
||||
commit_data = {
|
||||
"message": message,
|
||||
"tree": tree_sha,
|
||||
"parents": [parent_sha] if parent_sha else []
|
||||
}
|
||||
|
||||
commit_url = f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/git/commits"
|
||||
response = self.session.post(commit_url, json=commit_data)
|
||||
|
||||
if response.status_code != 201:
|
||||
raise Exception(f"Failed to create commit: {response.text}")
|
||||
|
||||
commit_sha = response.json()['sha']
|
||||
|
||||
# Update reference
|
||||
ref_data = {
|
||||
"sha": commit_sha,
|
||||
"force": False
|
||||
}
|
||||
|
||||
response = self.session.patch(ref_url, json=ref_data)
|
||||
|
||||
if response.status_code != 200:
|
||||
# Try to create the reference
|
||||
ref_url = f"{self.gitea_url}/api/v1/repos/{self.repo_owner}/{self.repo_name}/git/refs"
|
||||
ref_data = {
|
||||
"ref": "refs/heads/master",
|
||||
"sha": commit_sha
|
||||
}
|
||||
response = self.session.post(ref_url, json=ref_data)
|
||||
|
||||
if response.status_code != 201:
|
||||
raise Exception(f"Failed to update ref: {response.text}")
|
||||
|
||||
return commit_sha
|
||||
|
||||
def auto_commit(self, message=None, base_dir="."):
|
||||
"""Main auto-commit function using Go-Git API."""
|
||||
if not message:
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
message = f"Go-Git Auto-Commit: {timestamp}"
|
||||
|
||||
print(f"Go-Git Auto-Commit starting with message: {message}")
|
||||
print("=" * 60)
|
||||
|
||||
# Find changed files
|
||||
print("1. Scanning for changed files...")
|
||||
changed_files = self.find_changed_files(base_dir)
|
||||
|
||||
if not changed_files:
|
||||
print("No changes detected.")
|
||||
return True
|
||||
|
||||
print(f"Found {len(changed_files)} changed files:")
|
||||
for change_type, relative_path, _ in changed_files[:10]: # Show first 10
|
||||
print(f" {change_type}: {relative_path}")
|
||||
if len(changed_files) > 10:
|
||||
print(f" ... and {len(changed_files) - 10} more")
|
||||
|
||||
# Create commit
|
||||
print(f"\n2. Creating commit: '{message}'")
|
||||
try:
|
||||
commit_sha = self.create_commit(message, changed_files, base_dir)
|
||||
print(f"Commit created successfully: {commit_sha}")
|
||||
|
||||
# Show commit URL
|
||||
commit_url = f"{self.gitea_url}/{self.repo_owner}/{self.repo_name}/commit/{commit_sha}"
|
||||
print(f"Commit URL: {commit_url}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error creating commit: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
# Configuration
|
||||
GITEA_URL = "https://git.mtrcompute.com"
|
||||
USERNAME = "jleu3482"
|
||||
PASSWORD = "jleu1212"
|
||||
REPO_OWNER = "jleu3482"
|
||||
REPO_NAME = "railseek6"
|
||||
|
||||
# Get commit message from command line
|
||||
if len(sys.argv) > 1:
|
||||
message = sys.argv[1]
|
||||
else:
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
message = f"Go-Git Auto-Commit: {timestamp}"
|
||||
|
||||
print("Go-Git Auto-Commit Script for LightRAG")
|
||||
print("=" * 60)
|
||||
|
||||
# Initialize Go-Git client
|
||||
gogit = GoGitAutoCommit(GITEA_URL, USERNAME, PASSWORD, REPO_OWNER, REPO_NAME)
|
||||
|
||||
# Run auto-commit
|
||||
success = gogit.auto_commit(message)
|
||||
|
||||
if success:
|
||||
print("\n" + "=" * 60)
|
||||
print("Go-Git auto-commit completed successfully!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("\n" + "=" * 60)
|
||||
print("Go-Git auto-commit failed!")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user