From a43e8bc885bceddad0bf4e2e3147b36db4950f28 Mon Sep 17 00:00:00 2001 From: laily Date: Sat, 27 Jun 2026 11:55:41 +0800 Subject: [PATCH] feat: add git-setup --- script/git-setup.sh | 135 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 script/git-setup.sh diff --git a/script/git-setup.sh b/script/git-setup.sh new file mode 100755 index 0000000..ad2a675 --- /dev/null +++ b/script/git-setup.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# 交互式保存 Git HTTPS 凭据(主机、用户名、Token) + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck disable=SC1091 +source "$SCRIPT_DIR/common/help.sh" + +usage() { + cat <<'EOF' +用法: git-setup + +交互式输入 Git 主机、用户名、Token,写入系统凭据存储。 +写入后 HTTPS 克隆与 push 无需再输入密码。 + +需已配置 Git 凭据 helper(如先运行 ff script git-init 链接 dotfile 配置)。 +凭据由 ~/.dotfile/git/git-credential.sh 管理(Keychain / libsecret / store)。 + +示例主机: github.com、gitlab.com、gitee.com +也支持输入完整地址,如 https://github.com 或 git@github.com + +可重复运行以添加或更新其他主机凭据。 + +选项: + -h, --help 显示此帮助 +EOF +} + +dotfile_help_requested "${1:-}" && dotfile_show_help + +set -euo pipefail + +if ! command -v git >/dev/null 2>&1; then + echo "错误: 未找到 git,请先安装 Git" + exit 1 +fi + +if [[ ! -t 0 ]]; then + echo "错误: 请在交互式终端中运行此脚本" + exit 1 +fi + +normalize_git_host() { + local input="$1" + input="${input#https://}" + input="${input#http://}" + input="${input#git@}" + input="${input%%/*}" + input="${input%/}" + echo "$input" +} + +trim() { + local value="$1" + value="${value#"${value%%[![:space:]]*}"}" + value="${value%"${value##*[![:space:]]}"}" + printf '%s' "$value" +} + +prompt_required() { + local prompt="$1" + local var_name="$2" + local secret="${3:-}" + local value="" + + while [[ -z "$value" ]]; do + if [[ "$secret" == "secret" ]]; then + read -rsp "$prompt: " value + echo >&2 + else + read -rp "$prompt: " value + fi + value="$(trim "$value")" + if [[ -z "$value" ]]; then + echo "不能为空,请重新输入。" >&2 + fi + done + + printf -v "$var_name" '%s' "$value" +} + +store_git_credential() { + local host="$1" + local username="$2" + local token="$3" + + printf 'protocol=https\nhost=%s\nusername=%s\npassword=%s\n\n' \ + "$host" "$username" "$token" | git credential approve + + if [[ -f "$HOME/.git-credentials" ]]; then + chmod 600 "$HOME/.git-credentials" + fi +} + +verify_git_credential() { + local host="$1" + local username="$2" + local filled="" + + filled="$(printf 'protocol=https\nhost=%s\n\n' "$host" | git credential fill 2>/dev/null || true)" + if [[ "$filled" == *$'\n'"username=$username"$'\n'* ]]; then + return 0 + fi + return 1 +} + +echo "=== 保存 Git HTTPS 凭据 ===" +echo "凭据将保存到系统钥匙串;若不可用则回退到 ~/.git-credentials。" +echo "" + +prompt_required "Git 主机地址 (如 github.com)" GIT_HOST +GIT_HOST="$(normalize_git_host "$GIT_HOST")" + +if [[ -z "$GIT_HOST" ]]; then + echo "错误: 无法解析 Git 主机地址" + exit 1 +fi + +prompt_required "用户名" GIT_USERNAME +prompt_required "Token" GIT_TOKEN secret + +store_git_credential "$GIT_HOST" "$GIT_USERNAME" "$GIT_TOKEN" +unset GIT_TOKEN + +echo "" +if verify_git_credential "$GIT_HOST" "$GIT_USERNAME"; then + echo "✅ 凭据已保存: https://${GIT_USERNAME}@${GIT_HOST}" +else + echo "✅ 凭据已写入: https://${GIT_USERNAME}@${GIT_HOST}" + echo "提示: 部分凭据 helper 无法通过 fill 验证,但 clone/push 通常仍可用。" +fi + +echo "" +echo "可尝试:" +echo " git clone https://${GIT_HOST}//.git" +echo " git ls-remote https://${GIT_HOST}//.git"