mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 10:51:02 +01:00
feat: new button to push local branches, no longer auto pushes new branches to remote
This commit is contained in:
@@ -10,6 +10,7 @@ from ..settings_utils import save_settings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
bp = Blueprint('git', __name__, url_prefix='/git')
|
||||
|
||||
@@ -109,6 +110,20 @@ def delete_branch(branch_name):
|
||||
else:
|
||||
logger.error(f"Failed to delete branch: {result}")
|
||||
return jsonify({'success': False, 'error': result}), 400
|
||||
|
||||
@bp.route('/branch/push', methods=['POST'])
|
||||
def push_branch():
|
||||
data = request.json
|
||||
logger.debug(f"Received request to push branch: {data}")
|
||||
branch_name = data.get('branch')
|
||||
if not branch_name:
|
||||
return jsonify({"success": False, "error": "Branch name is required"}), 400
|
||||
|
||||
success, result = branch_manager.push(branch_name)
|
||||
if success:
|
||||
return jsonify({"success": True, "data": result}), 200
|
||||
else:
|
||||
return jsonify({"success": False, "error": result["error"]}), 500
|
||||
|
||||
@bp.route('/push', methods=['POST'])
|
||||
def push_files():
|
||||
|
||||
27
backend/app/git/branches/push.py
Normal file
27
backend/app/git/branches/push.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import git
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
def push_branch_to_remote(repo_path, branch_name):
|
||||
try:
|
||||
logger.debug(f"Attempting to push branch {branch_name} to remote")
|
||||
repo = git.Repo(repo_path)
|
||||
|
||||
# Check if the branch exists locally
|
||||
if branch_name not in repo.heads:
|
||||
return False, f"Branch '{branch_name}' does not exist locally."
|
||||
|
||||
# Push the branch to remote and set the upstream branch
|
||||
origin = repo.remote(name='origin')
|
||||
origin.push(refspec=f"{branch_name}:{branch_name}", set_upstream=True)
|
||||
|
||||
logger.debug(f"Successfully pushed branch to remote: {branch_name}")
|
||||
return True, {"message": f"Pushed branch to remote: {branch_name}"}
|
||||
except git.GitCommandError as e:
|
||||
logger.error(f"Git command error pushing branch to remote: {str(e)}", exc_info=True)
|
||||
return False, {"error": f"Error pushing branch to remote: {str(e)}"}
|
||||
except Exception as e:
|
||||
logger.error(f"Error pushing branch to remote: {str(e)}", exc_info=True)
|
||||
return False, {"error": f"Error pushing branch to remote: {str(e)}"}
|
||||
@@ -297,3 +297,12 @@ export const unlinkRepo = async (removeFiles = false) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const pushBranchToRemote = async (branchName) => {
|
||||
try {
|
||||
const response = await axios.post(`${API_BASE_URL}/git/branch/push`, { branch: branchName });
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Error pushing branch to remote:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
checkoutBranch,
|
||||
createBranch,
|
||||
deleteBranch,
|
||||
pushBranchToRemote,
|
||||
} from "../../api/api";
|
||||
import {
|
||||
ExternalLink,
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
GitBranchPlus,
|
||||
ArrowRightCircle,
|
||||
Loader,
|
||||
CloudUpload,
|
||||
} from "lucide-react";
|
||||
import Tooltip from "../ui/Tooltip";
|
||||
import Alert from "../ui/Alert";
|
||||
@@ -58,33 +60,23 @@ const SettingsBranchModal = ({
|
||||
setLoadingAction("");
|
||||
};
|
||||
|
||||
const handleCheckout = async (branchName, isNewBranch = false) => {
|
||||
const handleCheckout = async (branchName) => {
|
||||
setLoadingAction(`checkout-${branchName}`);
|
||||
try {
|
||||
const response = await checkoutBranch(branchName);
|
||||
if (response.success) {
|
||||
// Refresh branches after successful checkout
|
||||
await fetchBranches();
|
||||
// Notify parent component to update the status
|
||||
onBranchChange(); // <-- Call the callback to update status in the parent component
|
||||
if (!isNewBranch) {
|
||||
Alert.success("Branch checked out successfully");
|
||||
}
|
||||
onClose(); // Close the modal
|
||||
onBranchChange();
|
||||
Alert.success("Branch checked out successfully");
|
||||
onClose();
|
||||
} else {
|
||||
Alert.error(response.error); // Use the Alert component for error
|
||||
Alert.error(response.error);
|
||||
}
|
||||
} catch (error) {
|
||||
if (
|
||||
error.response &&
|
||||
error.response.status === 400 &&
|
||||
error.response.data.error
|
||||
) {
|
||||
Alert.error(error.response.data.error); // Show alert with specific backend error message
|
||||
if (error.response && error.response.status === 400 && error.response.data.error) {
|
||||
Alert.error(error.response.data.error);
|
||||
} else {
|
||||
Alert.error(
|
||||
"An unexpected error occurred while checking out the branch."
|
||||
);
|
||||
Alert.error("An unexpected error occurred while checking out the branch.");
|
||||
console.error("Error checking out branch:", error);
|
||||
}
|
||||
} finally {
|
||||
@@ -98,24 +90,19 @@ const SettingsBranchModal = ({
|
||||
try {
|
||||
const response = await createBranch(newBranchName, branchOffMode);
|
||||
if (response.success) {
|
||||
// Checkout the new branch without showing the checkout alert
|
||||
await handleCheckout(newBranchName, true);
|
||||
Alert.success("Branch created and checked out successfully");
|
||||
await fetchBranches();
|
||||
onBranchChange();
|
||||
Alert.success("Branch created successfully");
|
||||
resetForm();
|
||||
} else {
|
||||
Alert.error(response.error); // Handle known errors from the backend
|
||||
Alert.error(response.error);
|
||||
}
|
||||
} catch (error) {
|
||||
if (
|
||||
error.response &&
|
||||
error.response.status === 400 &&
|
||||
error.response.data.error
|
||||
) {
|
||||
Alert.error(error.response.data.error); // Specific error from the backend
|
||||
if (error.response && error.response.status === 400 && error.response.data.error) {
|
||||
Alert.error(error.response.data.error);
|
||||
} else {
|
||||
console.error("Error branching off:", error); // Log unexpected errors
|
||||
Alert.error(
|
||||
"An unexpected error occurred while creating the branch. Please try again."
|
||||
);
|
||||
console.error("Error branching off:", error);
|
||||
Alert.error("An unexpected error occurred while creating the branch. Please try again.");
|
||||
}
|
||||
} finally {
|
||||
setLoadingAction("");
|
||||
@@ -155,12 +142,12 @@ const SettingsBranchModal = ({
|
||||
try {
|
||||
const response = await deleteBranch(branchToDelete);
|
||||
if (response.success) {
|
||||
onBranchChange(); // <-- Call the callback to update status in the parent component
|
||||
await fetchBranches(); // Refresh the list after deletion
|
||||
onBranchChange();
|
||||
await fetchBranches();
|
||||
Alert.success(`Branch '${branchToDelete}' deleted successfully`);
|
||||
setBranchToDelete(null);
|
||||
} else {
|
||||
Alert.error(response.error); // Use the Alert component for error
|
||||
Alert.error(response.error);
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.error("An unexpected error occurred while deleting the branch.");
|
||||
@@ -170,6 +157,24 @@ const SettingsBranchModal = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushToRemote = async (branchName) => {
|
||||
setLoadingAction(`push-${branchName}`);
|
||||
try {
|
||||
const response = await pushBranchToRemote(branchName);
|
||||
if (response.success) {
|
||||
Alert.success(`Branch '${branchName}' pushed to remote successfully`);
|
||||
await fetchBranches();
|
||||
} else {
|
||||
Alert.error(response.error);
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.error("An unexpected error occurred while pushing the branch to remote.");
|
||||
console.error("Error pushing branch to remote:", error);
|
||||
} finally {
|
||||
setLoadingAction("");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} title="Manage Git Branches">
|
||||
<div className="space-y-6 text-sm">
|
||||
@@ -204,6 +209,13 @@ const SettingsBranchModal = ({
|
||||
>
|
||||
{branch.name || "Unknown Branch"}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{branch.isLocal && !branch.isRemote
|
||||
? "(Local)"
|
||||
: !branch.isLocal && branch.isRemote
|
||||
? "(Remote)"
|
||||
: "(Local & Remote)"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
{branch.name !== currentBranch && (
|
||||
@@ -234,22 +246,36 @@ const SettingsBranchModal = ({
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
{branch.name !== currentBranch &&
|
||||
branch.name.toLowerCase() !== "main" && (
|
||||
<Tooltip content="Delete">
|
||||
<button
|
||||
onClick={() => confirmDeleteBranch(branch.name)}
|
||||
className="p-1.5 bg-red-500 text-white rounded-md hover:bg-red-600 hover:scale-105 transition-all duration-200 shadow-sm"
|
||||
disabled={loadingAction === `delete-${branch.name}`}
|
||||
>
|
||||
{loadingAction === `delete-${branch.name}` ? (
|
||||
<Loader size={16} className="animate-spin" />
|
||||
) : (
|
||||
<Trash2 size={16} />
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{branch.isLocal && !branch.isRemote && (
|
||||
<Tooltip content="Push to Remote">
|
||||
<button
|
||||
onClick={() => handlePushToRemote(branch.name)}
|
||||
className="p-1.5 bg-purple-500 text-white rounded-md hover:bg-purple-600 hover:scale-105 transition-all duration-200 shadow-sm"
|
||||
disabled={loadingAction === `push-${branch.name}`}
|
||||
>
|
||||
{loadingAction === `push-${branch.name}` ? (
|
||||
<Loader size={16} className="animate-spin" />
|
||||
) : (
|
||||
<CloudUpload size={16} />
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{branch.isLocal && branch.name !== currentBranch && branch.name.toLowerCase() !== "main" && (
|
||||
<Tooltip content="Delete">
|
||||
<button
|
||||
onClick={() => confirmDeleteBranch(branch.name)}
|
||||
className="p-1.5 bg-red-500 text-white rounded-md hover:bg-red-600 hover:scale-105 transition-all duration-200 shadow-sm"
|
||||
disabled={loadingAction === `delete-${branch.name}`}
|
||||
>
|
||||
{loadingAction === `delete-${branch.name}` ? (
|
||||
<Loader size={16} className="animate-spin" />
|
||||
) : (
|
||||
<Trash2 size={16} />
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip content="View on GitHub">
|
||||
<button
|
||||
onClick={() => handleOpenInGitHub(branch.name)}
|
||||
@@ -323,4 +349,4 @@ const SettingsBranchModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsBranchModal;
|
||||
export default SettingsBranchModal;
|
||||
Reference in New Issue
Block a user