#!/bin/bash # Git Repository Setup Script for Gitea # Supports both tea CLI and traditional SSH/HTTPS authentication # Now with JSON configuration support set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration file path CONFIG_FILE="$(dirname "$0")/config.json" # Known Gitea URLs to check credentials for KNOWN_GITEA_URLS=("https://go-gitea.mywire.org" "http://192.168.88.97:3000") # Mode flags CHECKS_MODE=false # Function to print colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to install Git Credential Manager if needed install_credential_manager() { local script_dir="$(dirname "$0")" local installer="$script_dir/install-git-credential-manager.sh" if [[ -f "$installer" ]]; then print_status "Running Git Credential Manager installer..." "$installer" return $? else print_warning "Git Credential Manager installer not found at $installer" return 1 fi } # Function to install Tea CLI if needed install_tea_cli() { local script_dir="$(dirname "$0")" local installer="$script_dir/install-tea-cli.sh" if [[ -f "$installer" ]]; then print_status "Running Tea CLI installer..." "$installer" return $? else print_warning "Tea CLI installer not found at $installer" return 1 fi } # Function to show detailed credential status for known Gitea instances show_gitea_credential_status() { print_status "Checking credential status for known Gitea instances..." for url in "${KNOWN_GITEA_URLS[@]}"; do local domain=$(echo "$url" | sed 's|https://||' | sed 's|http://||') echo echo "Gitea Instance: $url" echo "Domain: $domain" echo "Credential Config Key: credential.https://$domain.helper" local helper=$(git config --global credential."https://$domain".helper 2>/dev/null) if [[ -n "$helper" ]]; then echo "Configured Helper: $helper" # Check if the helper command exists case "$helper" in "manager") if command_exists git-credential-manager; then echo "Helper Status: Available (Git Credential Manager)" else echo "Helper Status: Configured but not installed" fi ;; "osxkeychain") if [[ "$OSTYPE" == "darwin"* ]]; then echo "Helper Status: Available (macOS Keychain)" else echo "Helper Status: Not applicable on this OS" fi ;; "/usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring") if command_exists gnome-keyring-daemon; then echo "Helper Status: Available (GNOME Keyring)" else echo "Helper Status: Configured but GNOME Keyring not available" fi ;; *) if command_exists "$helper"; then echo "Helper Status: Available (Custom: $helper)" else echo "Helper Status: Configured but command not found: $helper" fi ;; esac print_success "Credentials configured for $url" else echo "Configured Helper: None" echo "Helper Status: Not configured" print_warning "No credentials configured for $url" fi done } # Function to check and setup credentials for known Gitea instances check_and_setup_known_gitea_credentials() { print_status "Checking credentials for known Gitea instances..." local credential_helper="" # Check for Git Credential Manager (GCM) if command_exists git-credential-manager; then credential_helper="manager" print_success "Found Git Credential Manager" # Check for platform-specific helpers elif [[ "$OSTYPE" == "darwin"* ]] && git config --global --get credential.helper 2>/dev/null | grep -q "osxkeychain"; then credential_helper="osxkeychain" print_success "Found macOS Keychain credential helper" elif [[ "$OSTYPE" == "linux-gnu"* ]] && command_exists gnome-keyring-daemon; then credential_helper="/usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring" print_success "Found GNOME Keyring" # Fallback to generic manager elif git config --global --get credential.helper >/dev/null 2>&1; then credential_helper=$(git config --global --get credential.helper) print_success "Using existing credential helper: $credential_helper" else print_warning "No credential manager found" # Offer to install Git Credential Manager echo read -p "Would you like to install Git Credential Manager for secure credential storage? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if install_credential_manager; then credential_helper="manager" print_success "Git Credential Manager installed successfully" else print_warning "Failed to install Git Credential Manager" return 1 fi else print_warning "Skipping credential setup for known instances" return 1 fi fi for url in "${KNOWN_GITEA_URLS[@]}"; do local domain=$(echo "$url" | sed 's|https://||' | sed 's|http://||') if git config --global credential."https://$domain".helper >/dev/null 2>&1; then print_success "Credentials already configured for $url" else print_status "Configuring credentials for $url" local cmd="git config --global credential.\"https://$domain\".helper \"$credential_helper\"" echo "Running: $cmd" eval "$cmd" print_success "Credentials configured for $url" fi done return 0 } # Function to detect and configure credential manager setup_credential_manager() { print_status "Checking for Git credential managers..." local credential_helper="" # Check for Git Credential Manager (GCM) if command_exists git-credential-manager; then credential_helper="manager" print_success "Found Git Credential Manager" # Check for platform-specific helpers elif [[ "$OSTYPE" == "darwin"* ]] && git config --global --get credential.helper 2>/dev/null | grep -q "osxkeychain"; then credential_helper="osxkeychain" print_success "Found macOS Keychain credential helper" elif [[ "$OSTYPE" == "linux-gnu"* ]] && command_exists gnome-keyring-daemon; then credential_helper="/usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring" print_success "Found GNOME Keyring" # Fallback to generic manager elif git config --global --get credential.helper >/dev/null 2>&1; then credential_helper=$(git config --global --get credential.helper) print_success "Using existing credential helper: $credential_helper" else print_warning "No credential manager found" # Offer to install Git Credential Manager echo read -p "Would you like to install Git Credential Manager for secure credential storage? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if install_credential_manager; then credential_helper="manager" print_success "Git Credential Manager installed successfully" else print_warning "Failed to install Git Credential Manager" return 1 fi else print_warning "Continuing without credential manager - you will be prompted for credentials" return 1 fi fi # Configure credential helper for the specific Gitea instance if [[ -n "$GITEA_URL" ]]; then local domain=$(echo "$GITEA_URL" | sed 's|https://||' | sed 's|http://||') git config --global credential."https://$domain".helper "$credential_helper" print_success "Configured credential manager for $domain" else git config --global credential.helper "$credential_helper" print_success "Configured global credential manager" fi return 0 } # Function to validate input validate_input() { if [[ -z "$1" ]]; then print_error "$2 cannot be empty" exit 1 fi } # Function to load configuration from JSON load_config() { if [[ -f "$CONFIG_FILE" ]]; then print_status "Loading configuration from $CONFIG_FILE" # Check if jq is available for JSON parsing if command_exists jq; then GITEA_URL=$(jq -r '.gitea.server_url' "$CONFIG_FILE") DEFAULT_LOGIN_NAME=$(jq -r '.gitea.default_login_name' "$CONFIG_FILE") LOGIN_METHOD=$(jq -r '.gitea.login_method' "$CONFIG_FILE") HAS_ACCESS_TOKEN=$(jq -r '.gitea.has_access_token' "$CONFIG_FILE") DEFAULT_AUTH_METHOD=$(jq -r '.gitea.default_auth_method' "$CONFIG_FILE") DEFAULT_BRANCH=$(jq -r '.git.default_branch' "$CONFIG_FILE") DEFAULT_PRIVATE=$(jq -r '.repository.default_private' "$CONFIG_FILE") # Expand $USER if present if [[ "$DEFAULT_LOGIN_NAME" == "\$USER" ]]; then DEFAULT_LOGIN_NAME="$USER" fi print_success "Configuration loaded successfully" return 0 else print_warning "jq not found. Install jq for JSON configuration support." return 1 fi else print_warning "Configuration file not found. Using interactive mode." return 1 fi } # Function to get current username get_current_username() { if command_exists git; then git config user.name 2>/dev/null || echo "$USER" else echo "$USER" fi } # Function to setup SSH key setup_ssh_key() { print_status "Setting up SSH key for Gitea authentication..." local key_path="$HOME/.ssh/id_ed25519" if [[ ! -f "$key_path" ]]; then print_status "Generating new ED25519 SSH key..." ssh-keygen -t ed25519 -C "$GIT_EMAIL" -f "$key_path" -N "" print_success "SSH key generated successfully" else print_warning "SSH key already exists at $key_path" fi echo print_status "Your public SSH key (copy this to Gitea):" echo "----------------------------------------" cat "$key_path.pub" echo "----------------------------------------" echo read -p "Press Enter after adding the SSH key to your Gitea account..." } # Function to setup tea CLI setup_tea() { print_status "Setting up Tea CLI..." if ! command_exists tea; then print_warning "Tea CLI is not installed" # Offer to install Tea CLI echo read -p "Would you like to install Tea CLI for Gitea repository management? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if install_tea_cli; then print_success "Tea CLI installed successfully" else print_error "Failed to install Tea CLI" return 1 fi else print_warning "Continuing without Tea CLI - you can install it later with ./install-tea-cli.sh" return 1 fi else print_success "Tea CLI is already installed" fi # Configure tea login with presets print_status "Configuring Tea CLI login..." # Use defaults from config if available local tea_url="${GITEA_URL:-$GITEA_URL}" local tea_method="${LOGIN_METHOD:-token}" local tea_has_token="${HAS_ACCESS_TOKEN:-true}" echo "Using preset configuration:" echo "- URL: $tea_url" echo "- Method: $tea_method" echo "- Has token: $tea_has_token" echo # Check for existing logins print_status "Checking existing Tea CLI logins..." if tea logins 2>/dev/null | grep -q "No logins"; then echo "No existing logins found. Creating new login..." tea login add else echo "Existing logins found:" tea logins echo read -p "Do you want to use an existing login? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then read -p "Enter the name of the existing login to use: " existing_login if tea logins | grep -q "$existing_login"; then print_success "Using existing login: $existing_login" # Set the existing login as default for this session export TEA_LOGIN="$existing_login" else print_warning "Login '$existing_login' not found. Creating new login..." tea login add fi else echo "Creating new login..." tea login add fi fi } # Check for existing logins print_status "Checking existing tea logins..." if tea logins 2>/dev/null | grep -q "No logins"; then echo "No existing logins found. Creating new login..." tea login add else echo "Existing logins found:" tea logins echo read -p "Do you want to use an existing login? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then read -p "Enter the name of the existing login to use: " existing_login if tea logins | grep -q "$existing_login"; then print_success "Using existing login: $existing_login" # Set the existing login as default for this session export TEA_LOGIN="$existing_login" else print_warning "Login '$existing_login' not found. Creating new login..." tea login add fi else echo "Creating new login..." tea login add fi fi } # Function to initialize git repository init_git_repo() { print_status "Initializing git repository..." if [[ -d ".git" ]]; then print_warning "Git repository already exists" read -p "Do you want to reinitialize? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then rm -rf .git git init fi else git init fi # Configure git user if not set if [[ -z "$(git config user.name)" ]]; then git config user.name "$GIT_NAME" fi if [[ -z "$(git config user.email)" ]]; then git config user.email "$GIT_EMAIL" fi # Set default branch if specified if [[ -n "$DEFAULT_BRANCH" ]]; then git symbolic-ref HEAD "refs/heads/$DEFAULT_BRANCH" 2>/dev/null || true fi print_success "Git repository initialized" } # Function to add remote add_remote() { local remote_url="$1" local remote_name="${2:-origin}" print_status "Adding remote '$remote_name'..." # Check if remote already exists if git remote get-url "$remote_name" >/dev/null 2>&1; then print_warning "Remote '$remote_name' already exists" read -p "Do you want to update it? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then git remote set-url "$remote_name" "$remote_url" print_success "Remote '$remote_name' updated" fi else git remote add "$remote_name" "$remote_url" print_success "Remote '$remote_name' added" fi } # Function to create repository via tea CLI create_repo_tea() { local repo_name="$1" local repo_description="$2" local private="$3" local owner="$4" print_status "Creating repository '$repo_name' via tea CLI..." local cmd="tea repos create --name '$repo_name' --owner '$owner'" if [[ -n "$repo_description" ]]; then cmd="$cmd --description '$repo_description'" fi if [[ "$private" == "true" ]]; then cmd="$cmd --private" fi eval "$cmd" print_success "Repository created via tea CLI" } # Function to test connection test_connection() { local remote_url="$1" print_status "Testing connection to remote..." if [[ "$remote_url" == ssh* ]]; then # Test SSH connection local ssh_host=$(echo "$remote_url" | sed 's|ssh://git@||' | sed 's|:.*||' | sed 's|/.*||') if ssh -T "git@$ssh_host" 2>&1 | grep -q "successfully authenticated"; then print_success "SSH connection successful" else print_warning "SSH connection test failed, but you can still proceed" fi else # Test HTTPS connection (will prompt for credentials if not set up) print_status "HTTPS connection will be tested on first push/pull" fi } # Function to prompt with default prompt_with_default() { local prompt="$1" local default="$2" local var_name="$3" if [[ -n "$default" ]]; then read -p "$prompt [$default]: " input if [[ -z "$input" ]]; then input="$default" fi else read -p "$prompt: " input fi eval "$var_name='$input'" } # Function to parse command line arguments parse_args() { while [[ $# -gt 0 ]]; do case $1 in --checks) CHECKS_MODE=true shift ;; *) print_error "Unknown option: $1" echo "Usage: $0 [--checks]" exit 1 ;; esac done } # Main script main() { echo "========================================" echo "Git Repository Setup Script for Gitea" echo "========================================" echo # Parse command line arguments parse_args "$@" # Check if git is installed if ! command_exists git; then print_error "Git is not installed. Please install Git first." exit 1 fi # If checks mode, show status and exit if [[ "$CHECKS_MODE" == "true" ]]; then show_gitea_credential_status exit 0 fi # Check and setup credentials for known Gitea instances check_and_setup_known_gitea_credentials # Load configuration if available CONFIG_LOADED=false if load_config; then CONFIG_LOADED=true fi # Get user information echo "Please provide the following information:" echo prompt_with_default "Your name" "$(git config user.name 2>/dev/null)" "GIT_NAME" validate_input "$GIT_NAME" "Name" prompt_with_default "Your email" "$(git config user.email 2>/dev/null)" "GIT_EMAIL" validate_input "$GIT_EMAIL" "Email" prompt_with_default "Gitea username" "$DEFAULT_LOGIN_NAME" "GITEA_USERNAME" validate_input "$GITEA_USERNAME" "Gitea username" prompt_with_default "Gitea server URL" "$GITEA_URL" "GITEA_URL" validate_input "$GITEA_URL" "Gitea server URL" # Remove trailing slash GITEA_URL="${GITEA_URL%/}" prompt_with_default "Repository name" "$(basename "$(pwd)")" "REPO_NAME" validate_input "$REPO_NAME" "Repository name" read -p "Repository description (optional): " REPO_DESCRIPTION # Use default from config if available local default_private="$DEFAULT_PRIVATE" if [[ "$CONFIG_LOADED" != "true" ]]; then default_private="false" fi prompt_with_default "Private repository? (y/N)" "$default_private" "PRIVATE_INPUT" if [[ "$PRIVATE_INPUT" =~ ^[Yy]$ ]]; then PRIVATE="true" else PRIVATE="false" fi echo echo "Choose authentication method:" echo "1) SSH (recommended - passwordless after key setup)" echo "2) HTTPS with credential manager (secure, stores tokens)" echo "3) Tea CLI (creates repo via API)" # Use default auth method from config if available local auth_prompt="Enter your choice (1-3)" if [[ -n "$DEFAULT_AUTH_METHOD" ]]; then auth_prompt="$auth_prompt [$DEFAULT_AUTH_METHOD]" fi echo -n "$auth_prompt: " read -n 1 -r echo if [[ -z "$REPLY" && -n "$DEFAULT_AUTH_METHOD" ]]; then REPLY="$DEFAULT_AUTH_METHOD" fi case $REPLY in 1) AUTH_METHOD="ssh" print_status "SSH authentication selected" setup_ssh_key REMOTE_URL="ssh://git@${GITEA_URL#https://}/$GITEA_USERNAME/$REPO_NAME.git" ;; 2) AUTH_METHOD="https" print_status "HTTPS authentication selected" # Setup credential manager for passwordless authentication if setup_credential_manager; then print_success "Credential manager configured for passwordless HTTPS access" echo "You will be prompted for credentials on first use, then they will be stored securely." else print_warning "No credential manager available. You will be prompted for credentials each time." echo "Consider installing git-credential-manager for secure credential storage." fi REMOTE_URL="$GITEA_URL/$GITEA_USERNAME/$REPO_NAME.git" echo echo "HTTPS Authentication Setup:" echo "1. Generate a Personal Access Token in Gitea: User Settings → Applications" echo "2. Use your username and the access token when prompted" echo "3. Credentials will be stored securely by your credential manager" echo ;; 3) AUTH_METHOD="tea" print_status "Tea CLI authentication selected" setup_tea create_repo_tea "$REPO_NAME" "$REPO_DESCRIPTION" "$PRIVATE" "$GITEA_USERNAME" REMOTE_URL="$GITEA_URL/$GITEA_USERNAME/$REPO_NAME.git" ;; *) print_error "Invalid choice" exit 1 ;; esac # Initialize git repository init_git_repo # Add remote add_remote "$REMOTE_URL" # Test connection test_connection "$REMOTE_URL" echo print_success "Setup completed successfully!" echo echo "Summary:" echo "- Repository initialized: $(pwd)" echo "- Remote URL: $REMOTE_URL" echo "- Authentication method: $AUTH_METHOD" echo "- Default branch: ${DEFAULT_BRANCH:-main}" echo echo "Next steps:" echo "1. Add your files to the repository: git add ." echo "2. Make initial commit: git commit -m 'Initial commit'" echo "3. Push to remote: git push -u origin ${DEFAULT_BRANCH:-main}" echo if [[ "$AUTH_METHOD" == "ssh" ]]; then echo "SSH setup reminder:" echo "- Make sure your SSH public key is added to your Gitea account" echo "- SSH key location: $HOME/.ssh/id_ed25519.pub" elif [[ "$AUTH_METHOD" == "https" ]]; then echo "HTTPS setup reminder:" echo "- Use your Personal Access Token as password when prompted" echo "- Credentials are stored securely by your credential manager" echo "- Generate tokens at: $GITEA_URL/user/settings/applications" fi } # Run main function main "$@"