247 lines
6.8 KiB
Bash
Executable File
247 lines
6.8 KiB
Bash
Executable File
#!/bin/zsh
|
||
# Script Version: 1.6
|
||
# Description: Pushes the current folder (e.g. /etc) to a nested Gitea repo using provided nesting arguments. Auto-creates the remote repo via Gitea API if missing.
|
||
|
||
# Set variables
|
||
# ========
|
||
|
||
# Try to extract GITEA_API_TOKEN from ~/.gitea_token if not set
|
||
if [ -z "$GITEA_API_TOKEN" ] && [ -f "$HOME/.gitea_token" ]; then
|
||
GITEA_API_TOKEN=$(<"$HOME/.gitea_token")
|
||
export GITEA_API_TOKEN
|
||
fi
|
||
|
||
GITEA_USER=$(awk '{for(i=1;i<=NF;i++) if($i=="login") print $(i+1)}' ~/.netrc | head -n1)
|
||
if [ -z "$GITEA_USER" ]; then
|
||
echo "[ERROR] No login found in ~/.netrc"
|
||
exit 1
|
||
fi
|
||
|
||
GITEA_URL="https://$(awk '{for(i=1;i<=NF;i++) if($i=="machine") print $(i+1)}' ~/.netrc | head -n1)"
|
||
if [ -z "$GITEA_URL" ]; then
|
||
echo "[ERROR] No URL found in ~/.netrc"
|
||
exit 1
|
||
fi
|
||
GITEA_API_URL="$GITEA_URL/api/v1"
|
||
|
||
PRIVATE=false
|
||
DEBUG=false
|
||
COMMIT_MESSAGE="Update $(date +"%F_%T")"
|
||
|
||
# Logging function
|
||
# ========
|
||
log() {
|
||
local level="$1"; shift
|
||
if [[ "$level" == "DEBUG" && "$DEBUG" != true ]]; then return; fi
|
||
local color_reset="$(tput sgr0)"
|
||
local color=""
|
||
case "$level" in
|
||
INFO) color="$(tput setaf 6)" ;; # cyan (was green)
|
||
WARNING) color="$(tput setaf 3)" ;; # yellow
|
||
ERROR) color="$(tput setaf 1)" ;; # red
|
||
DEBUG) color="$(tput bold; tput setaf 4)" ;; # bold blue # green
|
||
WARNING) color="$(tput setaf 3)" ;; # yellow
|
||
ERROR) color="$(tput setaf 1)" ;; # red
|
||
DEBUG) color="$(tput setaf 4)" ;; # blue
|
||
esac
|
||
echo "${color}[$level] $*${color_reset}"
|
||
}
|
||
|
||
# Functions
|
||
# ========
|
||
create_repo() {
|
||
log INFO "Repository does not exist. Creating via API: $REMOTE_PATH"
|
||
log DEBUG "POST $GITEA_API_URL/user/repos with name=$REMOTE_PATH and private=$PRIVATE"
|
||
RESPONSE=$(curl -s -X POST \
|
||
-H "Authorization: token $GITEA_API_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"name\": \"$FOLDER_NAME\", \"private\": $PRIVATE}" \
|
||
"$GITEA_API_URL/user/repos")
|
||
|
||
if echo "$RESPONSE" | grep -q '"clone_url"'; then
|
||
log INFO "Remote repository created successfully."
|
||
HTTP_STATUS=200
|
||
else
|
||
log ERROR "Failed to create remote repository: $RESPONSE"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
prepare_commit() {
|
||
git add .
|
||
git diff --quiet HEAD
|
||
HAS_CHANGES=$?
|
||
if [ $HAS_CHANGES -eq 1 ] && ! git rev-parse --verify HEAD >/dev/null 2>&1; then
|
||
log INFO "Creating initial commit"
|
||
git commit -m "$COMMIT_MESSAGE"
|
||
elif [ $HAS_CHANGES -eq 1 ]; then
|
||
log INFO "Committing changes"
|
||
git commit -m "$COMMIT_MESSAGE"
|
||
else
|
||
log INFO "Nothing to commit"
|
||
fi
|
||
}
|
||
|
||
setup_remote() {
|
||
if git remote | grep -q '^origin$'; then
|
||
log INFO "Updating remote origin URL"
|
||
git remote set-url origin "$GIT_REMOTE"
|
||
else
|
||
log INFO "Adding remote origin"
|
||
git remote add origin "$GIT_REMOTE"
|
||
fi
|
||
}
|
||
|
||
push_changes() {
|
||
log INFO "Pushing to $GIT_REMOTE"
|
||
git push -u origin main
|
||
}
|
||
|
||
# Show help if no arguments are given
|
||
# ========
|
||
if [ $# -eq 0 ]; then
|
||
echo "GITEA_API_TOKEN=<your token>"
|
||
echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] <host_group>"
|
||
echo "Example: $0 server"
|
||
echo " $0 --private workstation"
|
||
echo " $0 --debug server"
|
||
echo " $0 --message \"minor update\" server"
|
||
echo
|
||
echo "Note: You must cd into the target folder before running this script."
|
||
echo "For example:"
|
||
echo " cd /etc && $0 server"
|
||
echo
|
||
echo "Authentication:"
|
||
echo " Git operations (clone, push, pull) use ~/.netrc with your Git password:"
|
||
echo " machine \$(echo \"$GITEA_URL\" | sed 's|https\?://||') login $GITEA_USER password \"<your Git password>\""
|
||
echo " chmod 600 ~/.netrc"
|
||
echo
|
||
echo " API operations (e.g. creating repos) use a Personal Access Token stored in ~/.gitea_token"
|
||
echo " echo \"<your_token>\" > ~/.gitea_token && chmod 600 ~/.gitea_token"
|
||
exit 0
|
||
fi
|
||
|
||
# Parse arguments
|
||
# ========
|
||
POSITIONAL_ARGS=()
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--private)
|
||
PRIVATE=true
|
||
shift
|
||
;;
|
||
--debug)
|
||
DEBUG=true
|
||
shift
|
||
;;
|
||
--message)
|
||
COMMIT_MESSAGE="$2"
|
||
shift 2
|
||
;;
|
||
*)
|
||
POSITIONAL_ARGS+=("$1")
|
||
shift
|
||
;;
|
||
esac
|
||
done
|
||
|
||
set -- "${POSITIONAL_ARGS[@]}"
|
||
|
||
if [[ $# -ne 1 ]]; then
|
||
echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] <host_group>"
|
||
exit 1
|
||
fi
|
||
|
||
HOST_GROUP=$(echo "$1" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')
|
||
HOST_NAME=$(hostname -s | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')
|
||
FOLDER_NAME="${HOST_NAME}-${HOST_GROUP}-$(basename "$PWD")"
|
||
REPO_PATH="$PWD"
|
||
REMOTE_PATH="$FOLDER_NAME"
|
||
GIT_REMOTE="$GITEA_URL/$GITEA_USER/$FOLDER_NAME.git"
|
||
|
||
# Git authentication hint
|
||
log DEBUG "Ensure ~/.netrc has: machine <host> login $GITEA_USER password <your Git password>"
|
||
|
||
# Check or create remote repo
|
||
check_or_create_repo() {
|
||
if [ -z "$GITEA_API_TOKEN" ]; then
|
||
log WARNING "GITEA_API_TOKEN is not set. Skipping API repo creation."
|
||
return
|
||
fi
|
||
|
||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
|
||
-H "Authorization: token $GITEA_API_TOKEN" \
|
||
"$GITEA_API_URL/repos/$GITEA_USER/$FOLDER_NAME")
|
||
|
||
if [ "$HTTP_STATUS" -ne 200 ]; then
|
||
create_repo
|
||
else
|
||
log INFO "Remote repository already exists."
|
||
fi
|
||
}
|
||
|
||
|
||
check_or_create_repo
|
||
|
||
# Main Process
|
||
# ========
|
||
|
||
# Ensure Git user identity is configured
|
||
log DEBUG "Checking Git user configuration..."
|
||
if ! git config user.name >/dev/null 2>&1; then
|
||
git config --global user.name "$(whoami)"
|
||
log DEBUG "Set Git user.name to $(whoami)"
|
||
else
|
||
log DEBUG "Git user.name already set to $(git config --show-origin user.name)"
|
||
fi
|
||
if ! git config user.email >/dev/null 2>&1; then
|
||
git config --global user.email "$(whoami)@$(hostname -f)"
|
||
log DEBUG "Set Git user.email to $(whoami)@$(hostname -f)"
|
||
else
|
||
log DEBUG "Git user.email already set to $(git config --show-origin user.email)"
|
||
fi
|
||
|
||
|
||
# Safety check against pushing from / or $HOME
|
||
if [[ "$PWD" == "$HOME" || "$PWD" == "/" ]]; then
|
||
log ERROR "Refusing to run inside \$PWD=$PWD"
|
||
exit 1
|
||
fi
|
||
log INFO "Pushing $REPO_PATH to $GIT_REMOTE"
|
||
cd "$REPO_PATH" || { log ERROR "Directory $REPO_PATH not found"; exit 1; }
|
||
|
||
# Initialize git if needed
|
||
# Branch is fixed to 'main' for simplicity and consistency
|
||
if [ ! -d .git ]; then
|
||
log INFO "Initializing Git repo"
|
||
git init
|
||
git config init.defaultBranch main
|
||
git checkout -b main
|
||
else
|
||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||
if [ "$CURRENT_BRANCH" != "main" ]; then
|
||
log WARNING "Current branch is '$CURRENT_BRANCH', renaming to 'main'"
|
||
git branch -m main
|
||
fi
|
||
log DEBUG ".git directory already present"
|
||
log DEBUG ".git directory already present"
|
||
fi
|
||
|
||
# Ensure at least one commit exists
|
||
prepare_commit
|
||
|
||
# Set or update remote
|
||
if [ "$HTTP_STATUS" -eq 200 ]; then
|
||
setup_remote
|
||
else
|
||
log WARNING "Skipping remote setup – repository does not exist."
|
||
fi
|
||
|
||
# Push to remote
|
||
if [ "$HTTP_STATUS" -eq 200 ]; then
|
||
push_changes
|
||
else
|
||
log WARNING "Skipping push – repository does not exist."
|
||
fi
|
||
|