refactor: move git operations into their own route

This commit is contained in:
Sam Chau
2024-09-03 21:08:39 +09:30
parent ec7430466f
commit fa4818cb6a
7 changed files with 195 additions and 242 deletions

View File

@@ -4,7 +4,7 @@ from .regex import bp as regex_bp
from .format import bp as format_bp
from .settings import bp as settings_bp
from .profile import bp as profile_bp
from .git.unlink_repo import repo_bp
from .git import bp as git_bp
import os
REGEX_DIR = os.path.join('data', 'db', 'regex_patterns')
@@ -14,17 +14,17 @@ PROFILE_DIR = os.path.join('data', 'db', 'profiles')
def create_app():
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})
# Initialize directories to avoid issues with non-existing directories
initialize_directories()
# Register Blueprints
app.register_blueprint(regex_bp)
app.register_blueprint(format_bp)
app.register_blueprint(settings_bp)
app.register_blueprint(profile_bp)
app.register_blueprint(repo_bp)
app.register_blueprint(git_bp)
return app
def initialize_directories():

View File

@@ -39,8 +39,10 @@ def handle_format(id):
saved_data = save_format(data)
return jsonify(saved_data)
elif request.method == 'DELETE':
logger.info("Received request to delete format with ID: %d", id)
result = delete_format(id)
if "error" in result:
logger.error("Error deleting format: %s", result['error'])
return jsonify(result), 400
return jsonify(result), 200

172
backend/app/git/__init__.py Normal file
View File

@@ -0,0 +1,172 @@
from flask import Blueprint, request, jsonify
from .status.status import get_git_status
from .status.diff import get_diff
from .branches.branches import Branch_Manager
from .operations.operations import GitOperations
from .unlink_repo import unlink_repository
import logging
logger = logging.getLogger(__name__)
bp = Blueprint('git', __name__, url_prefix='/git')
# Assume these are set up elsewhere, perhaps in a config file
REPO_PATH = '/app/data/db'
branch_manager = Branch_Manager(REPO_PATH)
git_operations = GitOperations(REPO_PATH)
@bp.route('/status', methods=['GET'])
def get_status():
logger.debug("Received request for git status")
success, message = get_git_status(REPO_PATH)
if success:
logger.debug("Successfully retrieved git status")
return jsonify({'success': True, 'data': message}), 200
else:
logger.error(f"Failed to retrieve git status: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/branch', methods=['POST'])
def create_branch():
branch_name = request.json.get('name')
base_branch = request.json.get('base', 'main')
logger.debug(f"Received request to create branch {branch_name} from {base_branch}")
success, result = branch_manager.create(branch_name, base_branch)
if success:
logger.debug(f"Successfully created branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to create branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/branches', methods=['GET'])
def get_branches():
logger.debug("Received request for branches")
success, result = branch_manager.get_all()
if success:
logger.debug("Successfully retrieved branches")
return jsonify({'success': True, 'data': result}), 200
else:
logger.error(f"Failed to retrieve branches: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/checkout', methods=['POST'])
def checkout_branch():
branch_name = request.json.get('branch')
logger.debug(f"Received request to checkout branch: {branch_name}")
success, result = branch_manager.checkout(branch_name)
if success:
logger.debug(f"Successfully checked out branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to checkout branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/branch/<branch_name>', methods=['DELETE'])
def delete_branch(branch_name):
logger.debug(f"Received request to delete branch: {branch_name}")
success, result = branch_manager.delete(branch_name)
if success:
logger.debug(f"Successfully deleted branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to delete branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/push', methods=['POST'])
def push_files():
files = request.json.get('files', [])
user_commit_message = request.json.get('commit_message', "Commit and push staged files")
logger.debug(f"Received request to push files: {files}")
commit_message = generate_commit_message(user_commit_message, files)
success, message = git_operations.push(files, commit_message)
if success:
logger.debug("Successfully committed and pushed files")
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error pushing files: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/revert', methods=['POST'])
def revert_file():
file_path = request.json.get('file_path')
if not file_path:
return jsonify({'success': False, 'error': "File path is required."}), 400
success, message = git_operations.revert(file_path)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error reverting file: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/revert-all', methods=['POST'])
def revert_all():
success, message = git_operations.revert_all()
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error reverting all changes: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/file', methods=['DELETE'])
def delete_file():
file_path = request.json.get('file_path')
if not file_path:
return jsonify({'success': False, 'error': "File path is required."}), 400
success, message = git_operations.delete(file_path)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error deleting file: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/pull', methods=['POST'])
def pull_branch():
branch_name = request.json.get('branch')
success, message = git_operations.pull(branch_name)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error pulling branch: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/diff', methods=['POST'])
def diff_file():
file_path = request.json.get('file_path')
try:
diff = get_diff(REPO_PATH, file_path)
logger.debug(f"Diff for file {file_path}: {diff}")
return jsonify({'success': True, 'diff': diff if diff else ""}), 200
except Exception as e:
logger.error(f"Error getting diff for file {file_path}: {str(e)}", exc_info=True)
return jsonify({'success': False, 'error': f"Error getting diff for file: {str(e)}"}), 400
@bp.route('/stage', methods=['POST'])
def handle_stage_files():
files = request.json.get('files', [])
success, message = git_operations.stage(files)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
return jsonify({'success': False, 'error': message}), 400
@bp.route('/unlink', methods=['POST'])
def unlink_repo():
success, message = unlink_repository(REPO_PATH)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
return jsonify({'success': False, 'error': message}), 400
def generate_commit_message(user_message, files):
file_changes = []
for file in files:
if 'regex_patterns' in file:
file_changes.append(f"Update regex pattern: {file.split('/')[-1]}")
elif 'custom_formats' in file:
file_changes.append(f"Update custom format: {file.split('/')[-1]}")
else:
file_changes.append(f"Update: {file}")
commit_message = f"{user_message}\n\nChanges:\n" + "\n".join(file_changes)
return commit_message

View File

@@ -2,6 +2,7 @@
import git
import logging
from flask import Blueprint, jsonify
logger = logging.getLogger(__name__)

View File

@@ -24,12 +24,4 @@ def unlink_repository(settings_manager):
return True, "Repository successfully unlinked"
except Exception as e:
logger.error(f"Error unlinking repository: {str(e)}", exc_info=True)
return False, f"Error unlinking repository: {str(e)}"
@repo_bp.route('/unlink', methods=['POST'])
def unlink_repo():
success, message = unlink_repository(repo_bp.settings_manager)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
return jsonify({'success': False, 'error': message}), 400
return False, f"Error unlinking repository: {str(e)}"

View File

@@ -2,20 +2,9 @@ import os
import yaml
import git
from flask import Blueprint, request, jsonify
from git.exc import GitCommandError, InvalidGitRepositoryError
import shutil
import subprocess
import logging
from datetime import datetime
import json
import requests
from .git.unlink_repo import repo_bp, unlink_repository
from .git.clone_repo import clone_repository
from .git.authenticate import validate_git_token
from .git.status.status import get_git_status
from .git.status.diff import get_diff
from .git.branches.branches import Branch_Manager
from .git.operations.operations import GitOperations
from .settings_utils import load_settings, save_settings
logging.basicConfig(level=logging.DEBUG)
@@ -35,51 +24,12 @@ class SettingsManager:
self.settings = load_settings()
self.repo_url = self.settings.get('gitRepo') if self.settings else None
self.repo_path = DB_DIR
self.branch_manager = Branch_Manager(self.repo_path)
self.git_operations = GitOperations(self.repo_path)
def clone_repository(self):
return clone_repository(self.repo_url, self.repo_path, self.settings["gitToken"])
def get_git_status(self):
return get_git_status(self.repo_path)
def get_branches(self):
return self.branch_manager.get_all()
def create_branch(self, branch_name, base_branch='main'):
return self.branch_manager.create(branch_name, base_branch)
def checkout_branch(self, branch_name):
return self.branch_manager.checkout(branch_name)
def delete_branch(self, branch_name):
return self.branch_manager.delete(branch_name)
def get_current_branch(self):
return self.branch_manager.get_current()
def stage_files(self, files):
return self.git_operations.stage(files)
def push_files(self, files, commit_message):
return self.git_operations.push(files, commit_message)
def revert_file(self, file_path):
return self.git_operations.revert(file_path)
def revert_all(self):
return self.git_operations.revert_all()
def delete_file(self, file_path):
return self.git_operations.delete(file_path)
def pull_branch(self, branch_name):
return self.git_operations.pull(branch_name)
settings_manager = SettingsManager()
repo_bp.settings_manager = settings_manager
@bp.route('', methods=['GET'])
def handle_settings():
@@ -121,166 +71,4 @@ def update_settings():
return jsonify({"error": message}), 400
except Exception as e:
logger.exception("Unexpected error in update_settings")
return jsonify({"error": f"Failed to update settings: {str(e)}"}), 500
@bp.route('/status', methods=['GET'])
def get_status():
logger.debug("Received request for git status")
success, message = settings_manager.get_git_status()
if success:
logger.debug("Successfully retrieved git status")
return jsonify({'success': True, 'data': message}), 200
else:
logger.error(f"Failed to retrieve git status: {message}")
return jsonify({'success': False, 'error': message}), 400
# Update the route handlers
@bp.route('/branch', methods=['POST'])
def create_branch():
branch_name = request.json.get('name')
base_branch = request.json.get('base', 'main')
logger.debug(f"Received request to create branch {branch_name} from {base_branch}")
success, result = settings_manager.create_branch(branch_name, base_branch)
if success:
logger.debug(f"Successfully created branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to create branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/branches', methods=['GET'])
def get_branches():
logger.debug("Received request for branches")
success, result = settings_manager.get_branches()
if success:
logger.debug("Successfully retrieved branches")
return jsonify({'success': True, 'data': result}), 200
else:
logger.error(f"Failed to retrieve branches: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/checkout', methods=['POST'])
def checkout_branch():
branch_name = request.json.get('branch')
logger.debug(f"Received request to checkout branch: {branch_name}")
success, result = settings_manager.checkout_branch(branch_name)
if success:
logger.debug(f"Successfully checked out branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to checkout branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/branch/<branch_name>', methods=['DELETE'])
def delete_branch(branch_name):
logger.debug(f"Received request to delete branch: {branch_name}")
success, result = settings_manager.delete_branch(branch_name)
if success:
logger.debug(f"Successfully deleted branch: {branch_name}")
return jsonify({'success': True, **result}), 200
else:
logger.error(f"Failed to delete branch: {result}")
return jsonify({'success': False, 'error': result}), 400
@bp.route('/current-branch', methods=['GET'])
def get_current_branch():
current_branch = settings_manager.get_current_branch()
if current_branch:
return jsonify({'success': True, 'current_branch': current_branch}), 200
else:
return jsonify({'success': False, 'error': 'Failed to get current branch'}), 400
@bp.route('/stage', methods=['POST'])
def stage_files():
files = request.json.get('files', [])
success, message = settings_manager.stage_files(files)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error staging files: {message}")
return jsonify({'success': False, 'error': message}), 400
def generate_commit_message(user_message, files):
file_changes = []
for file in files:
if 'regex_patterns' in file:
file_changes.append(f"Update regex pattern: {file.split('/')[-1]}")
elif 'custom_formats' in file:
file_changes.append(f"Update custom format: {file.split('/')[-1]}")
else:
file_changes.append(f"Update: {file}")
commit_message = f"{user_message}\n\nChanges:\n" + "\n".join(file_changes)
return commit_message
@bp.route('/push', methods=['POST'])
def push_files():
files = request.json.get('files', [])
user_commit_message = request.json.get('commit_message', "Commit and push staged files")
logger.debug(f"Received request to push files: {files}")
commit_message = generate_commit_message(user_commit_message, files)
success, message = settings_manager.push_files(files, commit_message)
if success:
logger.debug("Successfully committed and pushed files")
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error pushing files: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/revert', methods=['POST'])
def revert_file():
file_path = request.json.get('file_path')
if not file_path:
return jsonify({'success': False, 'error': "File path is required."}), 400
success, message = settings_manager.revert_file(file_path)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error reverting file: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/revert-all', methods=['POST'])
def revert_all():
success, message = settings_manager.revert_all()
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error reverting all changes: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/file', methods=['DELETE'])
def delete_file():
file_path = request.json.get('file_path')
if not file_path:
return jsonify({'success': False, 'error': "File path is required."}), 400
success, message = settings_manager.delete_file(file_path)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error deleting file: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/pull', methods=['POST'])
def pull_branch():
branch_name = request.json.get('branch')
success, message = settings_manager.pull_branch(branch_name)
if success:
return jsonify({'success': True, 'message': message}), 200
else:
logger.error(f"Error pulling branch: {message}")
return jsonify({'success': False, 'error': message}), 400
@bp.route('/diff', methods=['POST'])
def diff_file():
file_path = request.json.get('file_path')
try:
diff = get_diff(settings_manager.repo_path, file_path)
logger.debug(f"Diff for file {file_path}: {diff}")
return jsonify({'success': True, 'diff': diff if diff else ""}), 200
except Exception as e:
logger.error(f"Error getting diff for file {file_path}: {str(e)}", exc_info=True)
return jsonify({'success': False, 'error': f"Error getting diff for file: {str(e)}"}), 400
return jsonify({"error": f"Failed to update settings: {str(e)}"}), 500

View File

@@ -122,7 +122,7 @@ export const saveSettings = async (settings) => {
export const getGitStatus = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/settings/status`);
const response = await axios.get(`${API_BASE_URL}/git/status`);
return response.data;
} catch (error) {
console.error('Error fetching Git status:', error);
@@ -132,7 +132,7 @@ export const getGitStatus = async () => {
export const getBranches = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/settings/branches`);
const response = await axios.get(`${API_BASE_URL}/git/branches`);
return response.data;
} catch (error) {
console.error('Error fetching branches:', error);
@@ -142,7 +142,7 @@ export const getBranches = async () => {
export const checkoutBranch = async (branchName) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/checkout`, { branch: branchName });
const response = await axios.post(`${API_BASE_URL}/git/checkout`, { branch: branchName });
return response.data;
} catch (error) {
console.error('Error checking out branch:', error);
@@ -152,7 +152,7 @@ export const checkoutBranch = async (branchName) => {
export const createBranch = async (branchName, baseBranch) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/branch`, { name: branchName, base: baseBranch });
const response = await axios.post(`${API_BASE_URL}/git/branch`, { name: branchName, base: baseBranch });
return response.data;
} catch (error) {
console.error('Error creating branch:', error);
@@ -162,7 +162,7 @@ export const createBranch = async (branchName, baseBranch) => {
export const deleteBranch = async (branchName) => {
try {
const response = await axios.delete(`${API_BASE_URL}/settings/branch/${branchName}`);
const response = await axios.delete(`${API_BASE_URL}/git/branch/${branchName}`);
return response.data;
} catch (error) {
console.error('Error deleting branch:', error);
@@ -172,7 +172,7 @@ export const deleteBranch = async (branchName) => {
export const addFiles = async (files) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/stage`, { files });
const response = await axios.post(`${API_BASE_URL}/git/stage`, { files });
return response.data;
} catch (error) {
console.error('Error staging files:', error);
@@ -182,7 +182,7 @@ export const addFiles = async (files) => {
export const pushFiles = async (files, commitMessage) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/push`, {
const response = await axios.post(`${API_BASE_URL}/git/push`, {
files,
commit_message: commitMessage
});
@@ -195,10 +195,9 @@ export const pushFiles = async (files, commitMessage) => {
export const revertFile = async (filePath) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/revert`, {
const response = await axios.post(`${API_BASE_URL}/git/revert`, {
file_path: filePath
});
return response.data;
} catch (error) {
console.error('Error reverting file:', error);
@@ -208,8 +207,7 @@ export const revertFile = async (filePath) => {
export const revertAll = async () => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/revert-all`);
const response = await axios.post(`${API_BASE_URL}/git/revert-all`);
return response.data;
} catch (error) {
console.error('Error reverting all changes:', error);
@@ -219,7 +217,7 @@ export const revertAll = async () => {
export const deleteFile = async (filePath) => {
try {
const response = await axios.delete(`${API_BASE_URL}/settings/file`, {
const response = await axios.delete(`${API_BASE_URL}/git/file`, {
data: { file_path: filePath },
});
return response.data;
@@ -231,7 +229,7 @@ export const deleteFile = async (filePath) => {
export const pullBranch = async (branchName) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/pull`, { branch: branchName });
const response = await axios.post(`${API_BASE_URL}/git/pull`, { branch: branchName });
return response.data;
} catch (error) {
console.error('Error pulling branch:', error);
@@ -241,7 +239,7 @@ export const pullBranch = async (branchName) => {
export const getDiff = async (filePath) => {
try {
const response = await axios.post(`${API_BASE_URL}/settings/diff`, { file_path: filePath });
const response = await axios.post(`${API_BASE_URL}/git/diff`, { file_path: filePath });
return response.data;
} catch (error) {
console.error('Error fetching diff:', error);
@@ -291,7 +289,7 @@ export const deleteProfile = async (id) => {
export const unlinkRepo = async () => {
try {
const response = await axios.post(`${API_BASE_URL}/repository/unlink`);
const response = await axios.post(`${API_BASE_URL}/git/unlink`);
return response.data;
} catch (error) {
console.error('Error unlinking repository:', error);