commit ceb25b5cdbe0ab0ef12adaee144fc0776650ff0f from: vincent delft date: Thu Feb 19 16:56:05 2026 UTC initial commit commit - /dev/null commit + ceb25b5cdbe0ab0ef12adaee144fc0776650ff0f blob - /dev/null blob + 2672cbc8e9bc14a6d5f4e8857925a2365506f405 (mode 755) --- /dev/null +++ got_last_commit_file.py @@ -0,0 +1,136 @@ +#!/usr/local/bin/python3 +""" +CGI script to redirect to the latest version of a file in gotwebd +URL pattern: /file/?path=&file= +""" + +import os +import sys +import subprocess +import os.path +import time +from urllib.parse import parse_qs, unquote, urlencode + + +REPO_BASE = "/got/public" # full path is /var/www/got/public +DEBUG = 0 # from 0 to 9 +LOG_FID = open("/logs/cgi.log","a") # this will go into /var/www/logs/cgi.log + +def log(level, text): + if level <= DEBUG: + LOG_FID.write(f"{text}\n") + +def get_query_params(): + """Parse query string parameters""" + query_string = os.environ.get('QUERY_STRING', '') + params = parse_qs(query_string) + + # Get first value for each param (parse_qs returns lists) + repo = params.get('path', [''])[0] + file_path = params.get('file', [''])[0] + + #return unquote(repo), unquote(file_path) + return repo, file_path + +def get_latest_commit(repo_path): + """Get the latest commit hash from a got repository""" + try: + # Use got log to get latest commit + result = subprocess.run( + ['got', 'log', '-r', repo_path, '-l', '1'], + capture_output=True, + text=True, + timeout=5 + ) + + if result.returncode == 0: + # Parse first line: "commit " + for line in result.stdout.split('\n'): + if line.startswith('commit '): + return line.split()[1] + print("return code not null:", result.returncode) + return None + except Exception: + return None + +def send_response(status, content_type, body, location=None): + """Send HTTP response""" + print(f"Status: {status}") + if location: + print(f"Location: {location}") + print(f"Content-Type: {content_type}") + print() # Empty line between headers and body + print(body) + +def main(): + env = os.environ + log(0,f"{time.ctime()} - {env.get('REMOTE_ADDR','NA')} - {env.get('HTTP_USER_AGENT','NA')} - {env.get('REQUEST_METHOD','NA')} {env.get('SERVER_NAME','NA')}/{env.get('QUERY_STRING','NA')}") + # Parse parameters + repo, file_path = get_query_params() + log(1,'repo, file_path:%s %s' % (repo, file_path)) + + # Validate inputs + if not repo or not file_path: + log(0, '%s - reply 400 - ERROR:missing path and/or file parameters' % (time.ctime())) + send_response( + "400 Bad Request", + "text/plain", + "Error: Missing required parameters 'path' and/or 'file'" + ) + return + + # Build repository path + repo_path = os.path.join(REPO_BASE, repo) + log(1, 'repo_path:%s %s' % (repo_path, os.path.isdir(repo_path))) + + # Check if repository exists + if not os.path.isdir(repo_path): + log(0, '%s - reply 404 - ERROR:no repository found at %s' % (time.ctime(), repo_path)) + send_response( + "404 Not Found", + "text/plain", + f"Error: Repository '{repo}' not found" + ) + return + + # Get latest commit + commit = get_latest_commit(repo_path) + log(1, 'commit:%s' % (commit)) + + if not commit: + log(0, '%s - reply 500 - ERROR:no "commit" found in got log for %s' % (time.ctime(), repo_path)) + send_response( + "500 Internal Server Error", + "text/plain", + f"Error: Could not retrieve latest commit for repository '{repo}'" + ) + return + + # Build gotwebd URL + folder, filename = os.path.split(file_path) + if folder in ("/"): + folder = "" + params = { + "action": "blobraw", + "commit": commit, + "folder": folder, + "file": filename, + "path": repo + } + + log(1, 'params:%s' % (params)) + gotwebd_url = "/?" + urlencode(params) + log(0, '%s - reply 302 - %s' % (time.ctime(), gotwebd_url)) + #/?action=blobraw&commit={commit}&folder=&file={file_path}&path={repo}" + + # Send redirect + send_response( + "302 Found", + "text/plain", + "Redirecting to latest version...", + location=gotwebd_url + ) + LOG_FID.close() + +if __name__ == "__main__": + main()