diff --git a/GITEA-UPLOAD-GUIDE.md b/GITEA-UPLOAD-GUIDE.md new file mode 100644 index 0000000..24e48c9 --- /dev/null +++ b/GITEA-UPLOAD-GUIDE.md @@ -0,0 +1,410 @@ +# Gitea Upload Guide + +This guide explains how to upload files to the Gitea server at `192.168.68.53:3000`. + +## Authentication + +**Gitea Server:** `http://192.168.68.53:3000` +**API Base URL:** `http://192.168.68.53:3000/api/v1` +**Authentication Token:** `77d13be9a7dbae402cb21c08d9231047a645e050` + +**Important:** Always include the token in the `Authorization` header: +``` +Authorization: token 77d13be9a7dbae402cb21c08d9231047a645e050 +``` + +## Method 1: Create Repository and Upload Files via API (Recommended) + +This method works without requiring `git` to be installed on the client machine. + +### Step 1: Create Repository + +**Endpoint:** `POST /api/v1/user/repos` + +**Request:** +```bash +curl -X POST \ + -H "Authorization: token 77d13be9a7dbae402cb21c08d9231047a645e050" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "repository-name", + "description": "Repository description", + "private": false, + "auto_init": false + }' \ + http://192.168.68.53:3000/api/v1/user/repos +``` + +**Python Example:** +```python +import urllib.request +import json + +TOKEN = "77d13be9a7dbae402cb21c08d9231047a645e050" +GITEA_API = "http://192.168.68.53:3000/api/v1" +REPO_NAME = "repository-name" +USERNAME = "kyle" # Replace with actual username + +url = f"{GITEA_API}/user/repos" +data = json.dumps({ + "name": REPO_NAME, + "description": "Repository description", + "private": False, + "auto_init": False +}).encode('utf-8') + +req = urllib.request.Request(url, data=data) +req.add_header("Authorization", f"token {TOKEN}") +req.add_header("Content-Type", "application/json") + +with urllib.request.urlopen(req) as response: + result = json.loads(response.read().decode()) + print(f"Repository created: {result.get('full_name')}") +``` + +**Response Codes:** +- `201`: Repository created successfully +- `409`: Repository already exists (this is OK, you can proceed) +- `401`: Authentication failed (check token) +- `422`: Invalid repository name or data + +### Step 2: Upload Files + +**Endpoint:** `PUT /api/v1/repos/{owner}/{repo}/contents/{filepath}` + +**Important:** Files must be base64-encoded in the request body. + +**Python Example (Upload Single File):** +```python +import urllib.request +import json +import base64 +import os + +TOKEN = "77d13be9a7dbae402cb21c08d9231047a645e050" +GITEA_API = "http://192.168.68.53:3000/api/v1" +REPO = "kyle/repository-name" # Format: username/repo-name +FILENAME = "example.txt" +BRANCH = "main" + +# Read and encode file +with open(FILENAME, 'rb') as f: + content = f.read() +content_b64 = base64.b64encode(content).decode('utf-8') + +# Create/Update file +url = f"{GITEA_API}/repos/{REPO}/contents/{FILENAME}" +data = json.dumps({ + "message": f"Add {FILENAME}", + "content": content_b64, + "branch": BRANCH +}).encode('utf-8') + +req = urllib.request.Request(url, data=data) +req.add_header("Authorization", f"token {TOKEN}") +req.add_header("Content-Type", "application/json") + +try: + with urllib.request.urlopen(req) as response: + result = json.loads(response.read().decode()) + print(f"✓ {FILENAME} uploaded") +except urllib.error.HTTPError as e: + if e.code == 409: + # File exists, need to update it + # First get file SHA + get_url = f"{GITEA_API}/repos/{REPO}/contents/{FILENAME}?ref={BRANCH}" + get_req = urllib.request.Request(get_url) + get_req.add_header("Authorization", f"token {TOKEN}") + + with urllib.request.urlopen(get_req) as get_resp: + file_info = json.loads(get_resp.read().decode()) + sha = file_info.get('sha') + + # Update with SHA + update_data = json.dumps({ + "message": f"Update {FILENAME}", + "content": content_b64, + "sha": sha, + "branch": BRANCH + }).encode('utf-8') + + req = urllib.request.Request(url, data=update_data, method='PUT') + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + with urllib.request.urlopen(req) as update_resp: + print(f"✓ {FILENAME} updated") + else: + print(f"✗ Error {e.code}: {e.read().decode()}") +``` + +**Python Example (Upload Multiple Files):** +```python +import urllib.request +import urllib.parse +import json +import base64 +import os + +TOKEN = "77d13be9a7dbae402cb21c08d9231047a645e050" +GITEA_API = "http://192.168.68.53:3000/api/v1" +REPO = "kyle/repository-name" +BRANCH = "main" + +def upload_file(filename, repo, branch="main"): + """Upload a single file to Gitea""" + try: + # Read and encode file + with open(filename, 'rb') as f: + content = f.read() + content_b64 = base64.b64encode(content).decode('utf-8') + + # Try to create file + url = f"{GITEA_API}/repos/{repo}/contents/{filename}" + data = json.dumps({ + "message": f"Add {filename}", + "content": content_b64, + "branch": branch + }).encode('utf-8') + + req = urllib.request.Request(url, data=data) + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + try: + with urllib.request.urlopen(req) as response: + print(f"✓ {filename}") + return True + except urllib.error.HTTPError as e: + if e.code == 409: + # File exists, update it + get_url = f"{GITEA_API}/repos/{repo}/contents/{filename}?ref={branch}" + get_req = urllib.request.Request(get_url) + get_req.add_header("Authorization", f"token {TOKEN}") + + with urllib.request.urlopen(get_req) as get_resp: + file_info = json.loads(get_resp.read().decode()) + sha = file_info.get('sha') + + update_data = json.dumps({ + "message": f"Update {filename}", + "content": content_b64, + "sha": sha, + "branch": branch + }).encode('utf-8') + + req = urllib.request.Request(url, data=update_data, method='PUT') + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + with urllib.request.urlopen(req) as update_resp: + print(f"✓ {filename} (updated)") + return True + else: + print(f"✗ {filename} (HTTP {e.code})") + return False + except Exception as e: + print(f"✗ {filename} ({str(e)})") + return False + +# Upload all files in current directory +files_to_upload = [f for f in os.listdir('.') if os.path.isfile(f) and not f.startswith('.')] + +for filename in files_to_upload: + upload_file(filename, REPO, BRANCH) +``` + +## Method 2: Using Git (If Available) + +If `git` is installed on the client machine, you can use traditional git commands: + +### Step 1: Create Repository (via API or Web UI) + +Same as Method 1, Step 1. + +### Step 2: Clone and Push + +```bash +# Clone the repository +TOKEN="77d13be9a7dbae402cb21c08d9231047a645e050" +git clone http://${TOKEN}@192.168.68.53:3000/kyle/repository-name.git + +# Or add remote +cd /path/to/your/files +git init +git remote add origin http://${TOKEN}@192.168.68.53:3000/kyle/repository-name.git + +# Add, commit, and push +git add -A +git commit -m "Initial commit" +git branch -M main +git push -u origin main +``` + +## Complete Example Script + +Here's a complete Python script that creates a repo and uploads all files: + +```python +#!/usr/bin/env python3 +"""Complete Gitea upload script""" +import urllib.request +import urllib.parse +import json +import base64 +import os +import sys + +# Configuration +TOKEN = "77d13be9a7dbae402cb21c08d9231047a645e050" +GITEA_API = "http://192.168.68.53:3000/api/v1" +USERNAME = "kyle" # Change if different +REPO_NAME = "repository-name" # Change to desired repo name +BRANCH = "main" + +def create_repo(name, description="", private=False): + """Create a new repository""" + url = f"{GITEA_API}/user/repos" + data = json.dumps({ + "name": name, + "description": description, + "private": private, + "auto_init": False + }).encode('utf-8') + + req = urllib.request.Request(url, data=data) + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + try: + with urllib.request.urlopen(req) as response: + result = json.loads(response.read().decode()) + print(f"✓ Repository created: {result.get('full_name')}") + return True + except urllib.error.HTTPError as e: + if e.code == 409: + print(f"✓ Repository already exists: {USERNAME}/{name}") + return True + else: + print(f"✗ Failed to create repository: {e.code}") + print(e.read().decode()) + return False + +def upload_file(filename, repo, branch="main"): + """Upload or update a file""" + try: + with open(filename, 'rb') as f: + content = f.read() + content_b64 = base64.b64encode(content).decode('utf-8') + + url = f"{GITEA_API}/repos/{repo}/contents/{filename}" + + # Try to create + data = json.dumps({ + "message": f"Add {filename}", + "content": content_b64, + "branch": branch + }).encode('utf-8') + + req = urllib.request.Request(url, data=data) + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + try: + with urllib.request.urlopen(req) as response: + return True + except urllib.error.HTTPError as e: + if e.code == 409: + # Update existing file + get_url = f"{GITEA_API}/repos/{repo}/contents/{filename}?ref={branch}" + get_req = urllib.request.Request(get_url) + get_req.add_header("Authorization", f"token {TOKEN}") + + with urllib.request.urlopen(get_req) as get_resp: + file_info = json.loads(get_resp.read().decode()) + sha = file_info.get('sha') + + update_data = json.dumps({ + "message": f"Update {filename}", + "content": content_b64, + "sha": sha, + "branch": branch + }).encode('utf-8') + + req = urllib.request.Request(url, data=update_data, method='PUT') + req.add_header("Authorization", f"token {TOKEN}") + req.add_header("Content-Type", "application/json") + + with urllib.request.urlopen(req) as update_resp: + return True + else: + return False + except Exception: + return False + +# Main execution +if __name__ == '__main__': + # Create repository + if not create_repo(REPO_NAME, "Repository description"): + sys.exit(1) + + # Upload files + repo = f"{USERNAME}/{REPO_NAME}" + files = [f for f in os.listdir('.') if os.path.isfile(f) and not f.startswith('.')] + + uploaded = 0 + failed = 0 + + for filename in files: + if upload_file(filename, repo, BRANCH): + print(f"✓ {filename}") + uploaded += 1 + else: + print(f"✗ {filename}") + failed += 1 + + print(f"\nComplete: {uploaded} uploaded, {failed} failed") + print(f"Repository: http://192.168.68.53:3000/{repo}") +``` + +## Important Notes + +1. **Token Security:** The token has full access. Keep it secure and don't commit it to public repositories. + +2. **File Size Limits:** Gitea may have file size limits. Very large files (>100MB) may need to use Git LFS. + +3. **Branch Name:** Default branch is usually `main`. Check the repository settings if you need a different branch. + +4. **File Encoding:** Always base64-encode file contents when using the API. + +5. **Error Handling:** + - `409 Conflict`: File already exists (handle by updating with SHA) + - `401 Unauthorized`: Invalid or expired token + - `404 Not Found`: Repository doesn't exist (create it first) + +6. **Rate Limiting:** Gitea may rate-limit API requests. Add delays between uploads if uploading many files. + +## Quick Reference + +**Create Repository:** +``` +POST /api/v1/user/repos +Authorization: token 77d13be9a7dbae402cb21c08d9231047a645e050 +``` + +**Upload File:** +``` +PUT /api/v1/repos/{owner}/{repo}/contents/{filepath} +Authorization: token 77d13be9a7dbae402cb21c08d9231047a645e050 +Content-Type: application/json +Body: {"message": "...", "content": "", "branch": "main"} +``` + +**Update File:** +Same as upload, but include `"sha": ""` in the body. + +## Repository URL Format + +- **Clone URL:** `http://77d13be9a7dbae402cb21c08d9231047a645e050@192.168.68.53:3000/username/repo-name.git` +- **Web URL:** `http://192.168.68.53:3000/username/repo-name` +- **API URL:** `http://192.168.68.53:3000/api/v1/repos/username/repo-name`