Files
build_toochain/linux_shell/build_script/base/git.bash
T
2026-07-07 15:23:39 +08:00

372 lines
7.9 KiB
Bash

#!/bin/bash
# shellcheck disable=SC2155
if ! type "include" >/dev/null 2>&1; then
include() {
. "$(cd "$(dirname "$1")" && pwd)/${2}"
}
fi
include "${BASH_SOURCE[0]}" ../pragma_once.bash
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
include "${BASH_SOURCE[0]}" ./global_rely/export.bash
# shellcheck source=./global_rely/export.bash
# 目前只是使用第一个url
get_git_urls() {
local dep="$1"
local -n out_urls="$2"
case "$dep" in
llvm)
out_urls=(
"https://github.com/llvm/llvm-project.git"
"https://gitee.com/mirrors/llvm-project.git"
)
;;
gmp)
out_urls=(
# 这个需要登陆?没法注册
"https://gitlab.inria.fr/gmp/gmp.git"
)
;;
mpfr)
out_urls=(
"https://gitlab.inria.fr/mpfr/mpfr.git"
)
;;
mpc)
out_urls=(
"https://gitlab.inria.fr/mpc/mpc.git"
)
;;
llvm-project)
out_urls=(
"https://github.com/llvm/llvm-project"
"https://gitee.com/mirrors/llvm-project.git"
)
;;
linux)
out_urls=(
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git"
"https://mirrors.tuna.tsinghua.edu.cn/git/linux.git"
)
;;
glibc)
out_urls=(
"https://sourceware.org/git/glibc.git"
"https://mirrors.tuna.tsinghua.edu.cn/git/glibc.git"
)
;;
newlib-cygwin)
out_urls=(
"https://github.com/mirror/newlib-cygwin.git"
)
;;
mingw-w64)
out_urls=(
"https://github.com/mingw-w64/mingw-w64.git"
"https://mirrors.tuna.tsinghua.edu.cn/git/mingw-w64.git"
"https://git.code.sf.net/p/mingw-w64/mingw-w64"
)
;;
zlib)
out_urls=(
"https://github.com/madler/zlib.git"
"https://gitee.com/mirrors/zlib.git"
)
;;
libxml2)
out_urls=(
"https://gitlab.gnome.org/GNOME/libxml2.git"
"https://gitee.com/mirrors/libxml2.git"
)
;;
musl)
out_urls=(
"https://git.musl-libc.org/git/musl"
)
;;
binutils-gdb)
out_urls=(
"https://sourceware.org/git/binutils-gdb.git"
"https://mirrors.tuna.tsinghua.edu.cn/git/binutils-gdb.git"
)
;;
gcc)
out_urls=(
"https://gcc.gnu.org/git/gcc.git"
"https://gitee.com/mirrors/gcc.git"
)
;;
windows-msvc-sysroot)
out_urls=(
"https://github.com/trcrsired/windows-msvc-sysroot.git"
)
;;
cppwinrt)
out_urls=(
"https://github.com/microsoft/cppwinrt.git"
"https://gitee.com/qabeowjbtkwb/cppwinrt.git"
)
;;
Qt)
out_urls=(
"https://github.com/qt/qt5.git"
)
;;
cpython)
out_urls=(
"https://github.com/python/cpython.git"
)
;;
cef)
out_urls=(
"https://github.com/chromiumembedded/cef.git"
)
;;
*)
log_error "未知依赖:${dep}"
return 1
;;
esac
}
get_repo_refs_local() {
local repo_dir="$1"
local -n out_branches="$2"
local -n out_tags="$3"
if [[ ! -d "${repo_dir}/.git" ]]; then
log_error "不是 git 仓库: ${repo_dir}"
return 1
fi
pushd "$repo_dir" >/dev/null || return 1
mapfile -t out_branches < <(
git branch --format='%(refname:short)'
)
mapfile -t out_tags < <(
git tag --sort=-version:refname
)
popd >/dev/null
}
get_repo_refs_remote() {
local repo_url="$1"
local -n out_branches="$2"
local -n out_tags="$3"
if [[ -z "$repo_url" ]]; then
log_error "repo_url 为空"
return 1
fi
mapfile -t out_branches < <(
git ls-remote --heads "$repo_url" |
awk '{print $2}' |
sed 's#refs/heads/##'
)
mapfile -t out_tags < <(
git ls-remote --tags "$repo_url" |
grep -v '\^{}' |
awk '{print $2}' |
sed 's#refs/tags/##'
)
}
repo_has_ver_local() {
local repo_dir="$1"
local ver="$2"
local branches=()
local tags=()
get_repo_refs_local "$repo_dir" branches tags || return 1
for b in "${branches[@]}"; do
[[ "$b" == "$ver" ]] && return 0
done
for t in "${tags[@]}"; do
[[ "$t" == "$ver" ]] && return 0
done
return 1
}
repo_has_ver_remote() {
local repo_url="$1"
local ver="$2"
local branches=()
local tags=()
get_repo_refs_remote "$repo_url" branches tags || return 1
for b in "${branches[@]}"; do
[[ "$b" == "$ver" ]] && return 0
done
for t in "${tags[@]}"; do
[[ "$t" == "$ver" ]] && return 0
done
return 1
}
print_repo_refs_local() {
local repo_dir="${1:-.}"
log_info "========== 本地仓库信息 =========="
log_info "路径: 【${repo_dir}"
if [[ ! -d "${repo_dir}/.git" ]]; then
log_error "不是 git 仓库"
return 1
fi
pushd "$repo_dir" >/dev/null || return 1
log_info "\n当前 HEAD:"
git rev-parse --short HEAD
log_info "\n当前分支:"
git branch --show-current
popd >/dev/null
local branches=()
local tags=()
get_repo_refs_local "$repo_dir" branches tags
log_info "本地 Branch:"
printf '%s' "${branches[@]:0:20}"
log_info "Tag 列表:"
printf '%s' "${tags[@]:0:20}"
log_info "远端地址:"
git -C "$repo_dir" remote -v
}
print_array_in_columns() {
local -n arr_ref="$1"
local cols="${2:-3}"
if ((cols < 1)); then
cols=1
fi
local count="${#arr_ref[@]}"
if ((count == 0)); then
printf '无\n'
return 0
fi
local max_width=0
local item
for item in "${arr_ref[@]}"; do
if ((${#item} > max_width)); then
max_width="${#item}"
fi
done
local cell_width=$((max_width + 2))
local rows=$(((count + cols - 1) / cols))
local r c idx
for ((r = 0; r < rows; r++)); do
for ((c = 0; c < cols; c++)); do
idx=$((c * rows + r))
if ((idx < count)); then
printf "%-*s" "$cell_width" "${arr_ref[idx]}"
fi
done
printf '\n'
done
}
print_repo_refs_remote() {
local repo_url="$1"
local cols="${2:-4}"
log_info "========== 远端仓库信息 =========="
log_info "URL: 【$repo_url"
local branches=()
local tags=()
get_repo_refs_remote "$repo_url" branches tags || return 1
log_info "远端 Branch:"
print_array_in_columns branches "$cols"
log_info "远端 Tag:"
print_array_in_columns tags "$cols"
}
get_latest_git_tag() {
local repo_url="$1"
git ls-remote --tags "$repo_url" |
grep -v '\^{}' |
awk '{print $2}' |
sed 's#refs/tags/##' |
sort -V |
tail -n 1
}
export use_network=1
# ver 指的是 git 的 branch 或者 tag
ensure_repo_version() {
local -n repo_dir=$1
local dep="$2"
local ver="$3"
repo_dir="${_git_cache_dir_}/${dep}"
local urls=()
log_info "ensure_repo_version ${dep} ${ver}"
get_git_urls "$dep" urls || return 1
local repo_url="${urls[0]}"
# CHECK_REPO
# CHECK_LOCAL
log_info "检查是否需要克隆"
if [[ ! -d "$repo_dir/.git" ]]; then
log_info "克隆仓库: $repo_url$repo_dir"
if ! exec_record "git clone --origin origin \"$repo_url\" \"$repo_dir\" "; then
log_error "clone 失败"
return 1
fi
fi
# CHECK_LOCAL
log_info "测试本地是否有版本"
if repo_has_ver_local "$repo_dir" "$ver"; then
log_info "checkout $ver"
exec_record "git -C \"$repo_dir\" checkout \"$ver\" " || {
log_error "checkout 失败"
return 1
}
return 0
fi
# FETCH
log_info "fetch 更新仓库"
if ! exec_record "git -C \"$repo_dir\" fetch --tags origin"; then
log_error "fetch 失败"
return 1
fi
if repo_has_ver_remote "$repo_dir" "${ver}"; then
:
else
log_error "远端仓库不存在版本: $ver"
print_repo_refs_remote "$repo_dir"
#exec_record " git ls-remote ${repo_url}"
return 3
fi
# CHECK_LOCAL AGAIN
if repo_has_ver_local "$repo_dir" "$ver"; then
log_info "checkout $ver"
exec_record "git -C \"$repo_dir\" checkout \"$ver\" " || {
log_error "checkout 失败"
return 1
}
return 0
fi
return 0
}
#configure_git_repo(){
# local dep="$1"
# local ver="$2"
# local opts="$3"
# ensure_repo_version "${dep}" "${ver}"
# local repo_dir="${_git_cache_dir_}/${dep}"
# configure_gnu_ex "${repo_dir}" "$opts"
#}