#!/bin/bash
# Android源码上传到GitLab自动化脚本
# 作者: Xupz
# 版本: 1.4
# 更新: 修复Git LFS选择逻辑,确保尊重用户选择
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 日志函数
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
log_debug() { echo -e "${CYAN}[DEBUG]${NC} $1"; }
# 配置变量(用户可修改)
DEFAULT_GITLAB_URL="git@192.168.xx.xxx:xxxx.git" # 目标git服务地址
USER_NAME="Xupz" # 你的用户名
USER_EMAIL="xxxx" # 你的邮箱地址
LARGE_FILE_THRESHOLD=1000M # 大文件阈值(1000MB)
# 全局变量
PROJECT_TYPE="" # 项目类型:android/regular
HAS_LARGE_FILES=false # 是否包含大文件
USER_SELECTED_LFS=false # 新增:记录用户LFS选择 [修复点1]
# 显示脚本信息
echo "================================================"
echo " Git项目上传自动化脚本 v1.4"
echo " 修复Git LFS选择逻辑,尊重用户选择"
echo "================================================"
echo
# 函数:检查Git配置是否已设置
check_git_config() {
log_step "检查Git配置..."
local needs_config=false
# 检查用户名配置
if ! git config --global user.name &>/dev/null; then
log_warn "全局Git用户名未配置"
needs_config=true
fi
# 检查邮箱配置
if ! git config --global user.email &>/dev/null; then
log_warn "全局Git邮箱未配置"
needs_config=true
fi
if [ "$needs_config" = false ]; then
log_info "✅ Git配置检查通过"
log_debug "用户名: $(git config --global user.name)"
log_debug "邮箱: $(git config --global user.email)"
return 0
else
return 1
fi
}
# 函数:配置Git用户信息
setup_git_config() {
log_step "配置Git用户信息..."
# 只有在需要时才配置
if ! git config --global user.name &>/dev/null; then
git config --global user.name "$USER_NAME"
log_info "已设置全局Git用户名: $USER_NAME"
fi
if ! git config --global user.email &>/dev/null; then
git config --global user.email "$USER_EMAIL"
log_info "已设置全局Git邮箱: $USER_EMAIL"
fi
# 配置大文件处理参数(始终配置)
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999
git config --global http.postBuffer 2097152000
git config --global http.maxRequestBuffer 2097152000
log_info "✅ Git配置完成"
}
# 函数:显示进度指示器(仅在分段提交阶段使用)
show_progress() {
local pid=$1
local message=$2
echo -n "$message "
# 显示进度点,直到进程结束
while kill -0 "$pid" 2>/dev/null; do
echo -n "."
sleep 3
done
echo " ✅"
}
# 函数:检测项目类型和检查大文件
detect_project_type() {
log_step "1. 检测项目类型和检查大文件..."
local android_files=("build" "device" "frameworks" "packages" "system" "hardware")
local found_count=0
for dir in "${android_files[@]}"; do
if [ -d "$dir" ]; then
found_count=$((found_count + 1))
log_debug "找到Android目录: $dir"
fi
done
if [ $found_count -ge 3 ]; then
PROJECT_TYPE="android"
log_info "✅ 检测到Android源码项目 (找到 $found_count/6 个核心目录)"
else
PROJECT_TYPE="regular"
log_info "📁 检测到普通项目"
fi
# 检查大文件
check_large_files
}
# 函数:检查大文件 [修复点2:完善LFS选择逻辑]
check_large_files() {
log_step "检查大文件..."
log_info "扫描大于 $LARGE_FILE_THRESHOLD 的文件..."
# 使用find命令查找大文件
local large_files=$(find . -type f -size +$LARGE_FILE_THRESHOLD 2>/dev/null | head -10)
local large_file_count=$(find . -type f -size +$LARGE_FILE_THRESHOLD 2>/dev/null | wc -l)
if [ "$large_file_count" -gt 0 ]; then
HAS_LARGE_FILES=true
log_warn "⚠️ 发现 $large_file_count 个大文件(> $LARGE_FILE_THRESHOLD)"
# 显示前10个大文件
if [ -n "$large_files" ]; then
log_info "大文件列表:"
echo "$large_files" | while read file; do
local size=$(du -h "$file" 2>/dev/null | cut -f1)
log_warn " $file ($size)"
done
fi
# 询问用户确认
echo
read -p "是否继续上传?大文件可能导致上传缓慢或失败 (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "操作已取消"
exit 0
fi
# 询问是否使用Git LFS [修复点3:正确记录用户选择]
read -p "是否设置Git LFS来管理大文件?(Y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]] || [ -z "$REPLY" ]; then
USER_SELECTED_LFS=true
log_info "用户选择使用Git LFS管理大文件"
else
USER_SELECTED_LFS=false
log_info "用户选择不使用Git LFS,大文件将通过普通Git管理"
fi
else
log_info "✅ 未发现大文件"
HAS_LARGE_FILES=false
USER_SELECTED_LFS=false
fi
}
# 函数:设置Git LFS
setup_git_lfs() {
log_step "设置Git LFS..."
if command -v git-lfs >/dev/null 2>&1; then
log_info "安装Git LFS..."
git lfs install
# 添加常见的大文件类型到LFS
git lfs track "*.zip"
git lfs track "*.tar.gz"
git lfs track "*.7z"
git lfs track "*.rar"
git lfs track "*.bin"
git lfs track "*.img"
git lfs track "*.iso"
git lfs track "*.apk"
log_info "✅ Git LFS配置完成"
else
log_warn "Git LFS未安装,跳过LFS设置"
log_info "你可以手动安装: sudo apt-get install git-lfs"
return 1
fi
}
# 函数:获取用户配置
get_user_config() {
log_step "2. 获取配置信息..."
# 显示项目类型
if [ "$PROJECT_TYPE" = "android" ]; then
log_info "项目类型: Android源码"
else
log_info "项目类型: 普通项目"
fi
# 显示LFS选择状态 [修复点4:增加状态提示]
if [ "$HAS_LARGE_FILES" = true ]; then
if [ "$USER_SELECTED_LFS" = true ]; then
log_info "Git LFS: 已启用"
else
log_info "Git LFS: 已禁用"
fi
fi
# GitLab地址
read -p "请输入GitLab仓库地址 [默认: $DEFAULT_GITLAB_URL]: " gitlab_url
GITLAB_URL=${gitlab_url:-$DEFAULT_GITLAB_URL}
# 用户名(仅在需要时询问)
if ! check_git_config; then
read -p "请输入Git用户名 [默认: $USER_NAME]: " user_name
USER_NAME=${user_name:-$USER_NAME}
else
log_info "使用现有Git配置"
fi
# 分支名称
read -p "请输入分支名称 [默认: main]: " branch_name
BRANCH_NAME=${branch_name:-"main"}
# 提交信息
if [ "$PROJECT_TYPE" = "android" ]; then
read -p "请输入初始提交信息 [默认: 初始提交: Android 13.0源码]: " commit_msg
COMMIT_MSG=${commit_msg:-"初始提交: Android 13.0源码"}
else
read -p "请输入初始提交信息 [默认: 初始提交]: " commit_msg
COMMIT_MSG=${commit_msg:-"初始提交"}
fi
log_info "配置完成:"
log_info " GitLab地址: $GITLAB_URL"
log_info " 分支: $BRANCH_NAME"
log_info " 项目类型: $PROJECT_TYPE"
if [ "$HAS_LARGE_FILES" = true ]; then
log_info " Git LFS: $([ "$USER_SELECTED_LFS" = true ] && echo "启用" || echo "禁用")"
fi
echo
}
# 函数:优化清理原有的Git/Repo信息
cleanup_existing_git() {
log_step "3. 彻底清理原有的Git和Repo信息..."
# 1. 删除所有.git目录(包括根目录)
log_info "清理所有.git目录..."
find . -name ".git" -type d -exec rm -rf {} + 2>/dev/null
local remaining_git=$(find . -name ".git" -type d 2>/dev/null | wc -l)
if [ $remaining_git -eq 0 ]; then
log_info "✅ 所有的.git目录已被删除。"
else
log_warn "⚠️ 仍有 $remaining_git 个.git目录未能删除"
fi
# 2. 删除.repo目录(仅Android项目需要)
if [ "$PROJECT_TYPE" = "android" ]; then
log_info "清理.repo目录..."
find . -name ".repo" -type d -exec rm -rf {} + 2>/dev/null
local remaining_repo=$(find . -name ".repo" -type d 2>/dev/null | wc -l)
if [ $remaining_repo -eq 0 ]; then
log_info "✅ 所有的.repo目录已被删除。"
else
log_warn "⚠️ 仍有 $remaining_repo 个.repo目录未能删除"
fi
fi
# 3. 删除Git LFS配置文件和对象
log_info "清理Git LFS配置..."
find . -wholename "*/.git/lfs" -type d -exec rm -rf {} + 2>/dev/null
local remaining_lfs=$(find . -wholename "*/.git/lfs" -type d 2>/dev/null | wc -l)
if [ $remaining_lfs -eq 0 ]; then
log_info "✅ 所有的Git LFS对象和配置已被删除。"
else
log_warn "⚠️ 仍有 $remaining_lfs 个Git LFS目录未能删除"
fi
log_info "✅ 清理完成,已清理Git/Repo相关项目"
}
# 函数:初始化Git仓库(使用验证过的命令)[修复点5:修复LFS自动设置问题]
init_git_repo() {
log_step "4. 初始化Git仓库..."
# 删除现有的.git目录(如果有)
if [ -d ".git" ]; then
log_info "删除现有.git目录..."
rm -rf .git
fi
# 初始化新仓库
log_info "执行git init..."
if git init; then
log_info "✅ Git仓库初始化成功"
else
log_error "Git仓库初始化失败"
exit 1
fi
# 配置Git用户信息(智能检查)
setup_git_config
# 修复:只有在用户明确选择使用LFS时才设置Git LFS
if [ "$HAS_LARGE_FILES" = true ] && [ "$USER_SELECTED_LFS" = true ] && command -v git-lfs >/dev/null 2>&1; then
log_info "应用用户选择的Git LFS设置..."
setup_git_lfs
elif [ "$HAS_LARGE_FILES" = true ] && [ "$USER_SELECTED_LFS" = true ] && ! command -v git-lfs >/dev/null 2>&1; then
log_warn "Git LFS未安装,但用户选择了使用LFS,将跳过LFS设置"
elif [ "$HAS_LARGE_FILES" = true ] && [ "$USER_SELECTED_LFS" = false ]; then
log_info "用户选择不使用Git LFS,大文件将通过普通Git管理"
fi
# 添加远程仓库
log_info "添加远程仓库: $GITLAB_URL"
if git remote add origin "$GITLAB_URL"; then
log_info "✅ 远程仓库配置成功"
else
log_error "远程仓库配置失败"
exit 1
fi
}
# 函数:Android项目的分阶段提交
android_staged_commit() {
log_step "5. 分阶段提交Android源码..."
echo "开始分阶段提交Android源码..."
echo "此过程可能较长时间,请耐心等待..."
echo
# 第一阶段:核心框架文件
log_info "第一阶段:提交核心框架文件..."
(
local added_files=false
local stage1_dirs=("build" "device" "frameworks" "system")
for dir in "${stage1_dirs[@]}"; do
if [ -d "$dir" ]; then
git add "$dir" 2>/dev/null && added_files=true
fi
done
# 添加构建文件
for pattern in "*.mk" "*.bp" "Android.mk" "Android.bp" "Makefile"; do
if ls $pattern 1> /dev/null 2>&1; then
git add $pattern 2>/dev/null && added_files=true
fi
done
if [ "$added_files" = true ]; then
git commit -m "${COMMIT_MSG} - 核心框架" >/dev/null 2>&1
else
exit 1
fi
) &
local stage1_pid=$!
show_progress $stage1_pid "处理核心框架"
if wait $stage1_pid; then
log_info "✅ 第一阶段提交完成"
else
log_warn "第一阶段无文件可提交,跳过"
fi
# 第二阶段:系统组件
log_info "第二阶段:提交系统组件..."
(
local added_files=false
local stage2_dirs=("bionic" "bootable" "development" "hardware" "packages")
for dir in "${stage2_dirs[@]}"; do
if [ -d "$dir" ]; then
git add "$dir" 2>/dev/null && added_files=true
fi
done
if [ "$added_files" = true ]; then
git commit -m "${COMMIT_MSG} - 系统组件" >/dev/null 2>&1
else
exit 1
fi
) &
local stage2_pid=$!
show_progress $stage2_pid "处理系统组件"
if wait $stage2_pid; then
log_info "✅ 第二阶段提交完成"
else
log_warn "第二阶段无文件可提交,跳过"
fi
# 第三阶段:其他组件
log_info "第三阶段:提交其他组件..."
(
local added_files=false
local stage3_dirs=("art" "cts" "dalvik" "external" "libcore" "prebuilts" "sdk" "tools" "vendor")
for dir in "${stage3_dirs[@]}"; do
if [ -d "$dir" ]; then
git add "$dir" 2>/dev/null && added_files=true
fi
done
if [ "$added_files" = true ]; then
git commit -m "${COMMIT_MSG} - 其他组件" >/dev/null 2>&1
else
exit 1
fi
) &
local stage3_pid=$!
show_progress $stage3_pid "处理其他组件"
if wait $stage3_pid; then
log_info "✅ 第三阶段提交完成"
else
log_warn "第三阶段无文件可提交,跳过"
fi
# 最终阶段:剩余所有文件
log_info "最终阶段:提交剩余文件..."
log_warn "⚠️ 此阶段可能需时较长,正在处理所有剩余文件..."
# 显示文件计数
local file_count=$(git status --porcelain 2>/dev/null | grep -c "??" || echo "0")
if [ "$file_count" -gt 0 ]; then
log_info "发现 $file_count 个未跟踪文件,正在添加..."
(
git add -A
git commit -m "${COMMIT_MSG} - 剩余文件" >/dev/null 2>&1
) &
local final_stage_pid=$!
show_progress $final_stage_pid "处理剩余文件"
if wait $final_stage_pid; then
log_info "✅ 最终阶段提交完成"
else
log_warn "最终阶段提交失败"
fi
else
log_warn "无剩余文件需要提交"
fi
# 显示提交统计
local commit_count=$(git log --oneline 2>/dev/null | wc -l || echo "0")
log_info "提交完成,共创建了 $commit_count 个提交"
}
# 函数:普通项目的一次性提交
regular_project_commit() {
log_step "5. 提交普通项目..."
echo "开始提交普通项目文件..."
echo "此过程可能较长时间,请耐心等待..."
echo
# 显示文件统计
local total_files=$(find . -type f -not -path "./.git/*" | wc -l)
local total_size=$(du -sh . | cut -f1)
log_info "项目统计:"
log_info " 文件数量: $total_files"
log_info " 总大小: $total_size"
echo
# 一次性添加所有文件
log_info "添加所有文件到Git..."
(
git add -A
git commit -m "$COMMIT_MSG" >/dev/null 2>&1
) &
local commit_pid=$!
show_progress $commit_pid "提交文件"
if wait $commit_pid; then
log_info "✅ 提交完成"
# 显示提交信息
local commit_hash=$(git rev-parse --short HEAD 2>/dev/null)
local file_count=$(git ls-files | wc -l)
log_info "提交哈希: $commit_hash"
log_info "跟踪文件数: $file_count"
else
log_error "提交失败"
exit 1
fi
}
# 函数:推送到远程仓库
push_to_remote() {
log_step "6. 推送到远程GitLab仓库..."
# 重命名分支
git branch -M "$BRANCH_NAME"
echo "开始推送代码到远程仓库..."
echo "这可能需要较长时间,请确保网络连接稳定..."
echo
# 显示推送估计信息
local total_commits=$(git log --oneline | wc -l)
local total_files=$(git ls-files | wc -l)
log_info "统计信息:"
log_info " 提交数量: $total_commits"
log_info " 文件数量: $total_files"
log_info " 项目类型: $PROJECT_TYPE"
if [ "$HAS_LARGE_FILES" = true ]; then
log_info " Git LFS: $([ "$USER_SELECTED_LFS" = true ] && echo "启用" || echo "禁用")"
fi
echo
# 执行推送(使用Git自带的进度显示)
log_info "开始推送过程..."
# 根据项目类型显示不同的提示
if [ "$PROJECT_TYPE" = "android" ]; then
log_warn "⚠️ Android项目较大,推送可能需时较长..."
elif [ "$HAS_LARGE_FILES" = true ]; then
if [ "$USER_SELECTED_LFS" = true ]; then
log_warn "⚠️ 项目包含大文件,已启用Git LFS管理..."
else
log_warn "⚠️ 项目包含大文件,但未启用Git LFS,推送可能较慢..."
fi
fi
# 直接使用Git的进度显示,不添加额外的进度指示
if git push -u origin "$BRANCH_NAME" --progress; then
log_info "✅ 代码推送成功!"
else
log_error "推送失败,请检查网络连接和仓库权限"
exit 1
fi
}
# 函数:验证推送结果
verify_push() {
log_step "7. 验证推送结果..."
# 获取最新状态
if git fetch origin 2>/dev/null; then
LOCAL_COMMIT=$(git rev-parse "$BRANCH_NAME" 2>/dev/null)
REMOTE_COMMIT=$(git rev-parse "origin/$BRANCH_NAME" 2>/dev/null)
if [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ] && [ -n "$LOCAL_COMMIT" ]; then
log_info "✅ 验证成功:本地和远程代码一致"
else
log_warn "⚠️ 本地和远程代码不一致或无法获取远程状态"
log_info "本地提交: ${LOCAL_COMMIT:0:8}"
log_info "远程提交: ${REMOTE_COMMIT:0:8}"
fi
else
log_warn "无法获取远程状态,但推送可能已成功"
fi
# 显示最终仓库信息
echo
log_info "最终仓库状态:"
git remote -v
echo
git branch -av
}
# 主执行函数
main() {
log_step "开始项目上传流程..."
# 设置异常处理
trap 'log_error "脚本执行中断"; exit 1' INT TERM
# 检测项目类型
detect_project_type
# 显示磁盘使用情况
local dir_size=$(du -sh . | cut -f1)
log_info "当前目录大小: $dir_size"
# 确认操作
read -p "是否继续上传流程?(y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "操作已取消"
exit 0
fi
# 执行各个步骤
get_user_config
cleanup_existing_git
init_git_repo
# 根据项目类型选择提交策略
if [ "$PROJECT_TYPE" = "android" ]; then
android_staged_commit
else
regular_project_commit
fi
push_to_remote
verify_push
# 完成提示
echo
echo "================================================"
log_info "🎉 项目上传完成!"
log_info "仓库地址: $GITLAB_URL"
log_info "分支: $BRANCH_NAME"
log_info "项目类型: $PROJECT_TYPE"
if [ "$HAS_LARGE_FILES" = true ]; then
log_info "大文件: 是 (Git LFS: $([ "$USER_SELECTED_LFS" = true ] && echo "启用" || echo "禁用"))"
else
log_info "大文件: 否"
fi
log_info "总耗时: ${SECONDS} 秒"
echo "================================================"
}
# 运行主函数
main "$@"
Android源码上传到GitLab自动化脚本
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
相关阅读更多精彩内容
- iOS 用Python脚本自动化打测试ipa包 1.在Mac上安装python环境 此部分不专门讲解,在网上能搜到...
- 项目内测阶段 代码托管在github apk上传到蒲公英应用平台 因为每次发布都要在studio里build完成再...
- android使用jenkins进行自动化打包 首先需要配置jdk,gradle,以及android sdk环境变...
- 需求:因为平时测试的时候需要将打的包上传到蒲公英,再将下载地址分享出来供大家下载,每次有小的修改就需要重新打包,然...
- jekins是大家众所周知的自动化工具,但我们这里讲的不是用Jekins打包而是用Mac自带的shell脚本方式实...