cvs-proxy/cvs_proxy/app.py

216 lines
No EOL
6 KiB
Python

from flask import Flask, request, jsonify, send_from_directory
from .cvs_client import CVSClient
import os
import sys
import argparse
# Get the directory where this app.py is located
app_dir = os.path.dirname(os.path.abspath(__file__))
# Get the parent directory (cvs-proxy root)
project_root = os.path.dirname(app_dir)
# UI directory path
ui_dir = os.path.join(project_root, 'ui')
app = Flask(__name__, static_folder=ui_dir, static_url_path='')
# Global variables to store configuration
cvs_client = None
app_config = {}
# Initialize CVS Client using provided parameters
def create_cvs_client(cvs_url, repos_checkout=None, cvs_module=None):
"""
Create CVS client from provided parameters
:param cvs_url: CVS repository URL
:type cvs_url: str
:param repos_checkout: Path to the directory where repositories will be checked out
:type repos_checkout: str, optional
:param cvs_module: CVS module to work with
:type cvs_module: str, optional
:return: Configured CVS Client
:rtype: CVSClient
:raises ValueError: If CVS URL is not provided
"""
if not cvs_url:
raise ValueError("CVS_URL must be provided as a command-line argument")
return CVSClient(cvs_url, repos_checkout=repos_checkout, cvs_module=cvs_module)
@app.route('/v1/tree', methods=['GET'])
def get_repository_tree():
"""
Get repository tree structure
Optional query param: module
"""
if not cvs_client:
return jsonify({"error": "CVS Client not initialized"}), 500
module = request.args.get('module')
try:
tree = cvs_client.list_repository_tree(module)
return jsonify(tree)
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/v1/diff', methods=['GET'])
def get_file_diff():
"""
Get diff between two revisions of a file
Required query params: file, rev1, rev2
"""
if not cvs_client:
return jsonify({"error": "CVS Client not initialized"}), 500
file_path = request.args.get('file')
rev1 = request.args.get('rev1')
rev2 = request.args.get('rev2')
if not all([file_path, rev1, rev2]):
return jsonify({"error": "Missing required parameters"}), 400
try:
diff = cvs_client.get_file_diff(file_path, rev1, rev2)
return jsonify({"diff": diff})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/v1/history', methods=['GET'])
def get_file_history():
"""
Get revision history for a file
Required query param: file
"""
if not cvs_client:
return jsonify({"error": "CVS Client not initialized"}), 500
file_path = request.args.get('file')
if not file_path:
return jsonify({"error": "Missing file parameter"}), 400
try:
history = cvs_client.get_file_history(file_path)
return jsonify(history)
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/v1/file', methods=['GET'])
def get_file_content():
"""
Get raw file content at a specific revision
Required param: file
Optional param: revision
"""
if not cvs_client:
return jsonify({"error": "CVS Client not initialized"}), 500
file_path = request.args.get('file')
revision = request.args.get('revision')
if not file_path:
return jsonify({"error": "Missing file parameter"}), 400
try:
content = cvs_client.get_file_content(file_path, revision)
return content
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/v1/health', methods=['GET'])
def health_check():
"""
Simple health check endpoint
"""
return jsonify({
"status": "healthy",
"cvs_client": "initialized" if cvs_client else "not initialized"
})
@app.route('/', methods=['GET'])
def index():
"""
Serve the UI index.html
"""
return send_from_directory(ui_dir, 'index.html')
@app.route('/<path:filename>', methods=['GET'])
def serve_static(filename):
"""
Serve static files (CSS, JS, etc.)
"""
return send_from_directory(ui_dir, filename)
def main():
"""
Main entry point for the CVS Proxy application
"""
global cvs_client, app_config
parser = argparse.ArgumentParser(
description='CVS Proxy - A web proxy for CVS repositories'
)
# CVS configuration arguments
parser.add_argument(
'--cvs-url',
required=True,
help='CVS repository URL (e.g., :pserver:user@host:/path/to/repo)'
)
parser.add_argument(
'--repo-checkouts',
default='/tmp/cvs_checkouts',
help='Path to the directory where repositories will be checked out (default: /tmp/cvs_checkouts)'
)
parser.add_argument(
'--cvs-module',
default=None,
help='CVS module to work with (optional)'
)
# Flask configuration arguments
parser.add_argument(
'--host',
default='0.0.0.0',
help='Flask host to bind to (default: 0.0.0.0)'
)
parser.add_argument(
'--port',
type=int,
default=5000,
help='Flask port to bind to (default: 5000)'
)
parser.add_argument(
'--debug',
action='store_true',
help='Enable Flask debug mode'
)
args = parser.parse_args()
# Store configuration
app_config = {
'cvs_url': args.cvs_url,
'repo_checkouts': args.repo_checkouts,
'cvs_module': args.cvs_module,
'host': args.host,
'port': args.port,
'debug': args.debug
}
# Attempt to create CVS client at startup
try:
cvs_client = create_cvs_client(
args.cvs_url,
repos_checkout=args.repo_checkouts,
cvs_module=args.cvs_module
)
except ValueError as e:
print(f"Error initializing CVS Client: {e}", file=sys.stderr)
cvs_client = None
print(f"Starting CVS Proxy on {args.host}:{args.port}")
app.run(host=args.host, port=args.port, debug=args.debug)
if __name__ == '__main__':
main()