Skip to content

Instantly share code, notes, and snippets.

@qijianpeng
Last active May 1, 2019 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qijianpeng/b65e9f41f1c615c826b12801ac569d6e to your computer and use it in GitHub Desktop.
Save qijianpeng/b65e9f41f1c615c826b12801ac569d6e to your computer and use it in GitHub Desktop.
Find the nearest common commit id to the MERGE_POINT
#
# Checks if differences occur between two branches.
#
# Usage:
# source ./build_utils.sh
# DIRECTORY="idbc"
# #before merge
# COMMON_COMMITS_ID=`common_branch_commit_id ur_branch_1 trunk/master`
# #after merge
# RES=`diferences_check $COMMON_COMMITS_ID HEAD $DIRECTORY`
#
# Gets the nearest common parent commit_id of two branches.
# before merge
function common_branch_commit_id(){
CURRENT_BRANCH_COMMIT_ID=$1
REMOTE_BRANCH_COMMIT_ID=$2
COMMON_COMMIT_ID=`git merge-base $CURRENT_BRANCH_COMMIT_ID $REMOTE_BRANCH_COMMIT_ID`
echo $COMMON_COMMIT_ID
}
# Checks differences between two commits.
#
# If any file of DIRECTORY has been changed from commit_a to commit_b, returns Y.
# otherwise, returns N.
function differences_check(){
FIRST_COMMIT_ID=$1
SECOND_COMMIT_ID=$2
DIRECTORY=$3
git diff --exit-code --name-only $FIRST_COMMIT_ID $SECOND_COMMIT_ID $DIRECTORY > /dev/null
if [[ $? == 1 ]]; then
echo "Y"
else
echo "N"
fi
}
#
# Gets latest commit id of last successful pipeline.
# INPUTS:
# TOKEN, PRIVATE-TOKEN of gitlab by curl.
# PRJ_NAME, project name. If project under some namespace, use ${NAMESPACE}%2F${PROJECT_NAME}.
# BRANCH_NAME, default is master.
#
function get_last_successed_pipeline_commit_id(){
set +e
TOKEN=$1
PRJ_NAME=$2
BRANCH_NAME=$3
if [[ $BRANCH_NAME == "" ]]; then BRANCH_NAME="master"; fi
PIPELINE_INFO=`curl --header "PRIVATE-TOKEN: ${TOKEN}" "http://172.16.1.41:10080/api/v4/projects/${PRJ_NAME}/pipelines?scope=finished&status=success&ref=${BRANCH_NAME}&per_page=1&page=1"`
COMMIT_ID=`awk -F '"' '{print $6}' ${PIPELINE_INFO}`
set -e
echo ${COMMIT_ID}
}
# Find the nearest common commit id to the MERGE_POINT.
# Assume the following history exists and the current branch is "master":
# 5 branch_2
# / \
# 3---6---M1---7 branch_1
# / \
# 1---2---4------------M2---8 master
#
# Usages and explanations:
# nearest_common_commit_to_merge_point M1 returns 3,
# nearest_common_commit_to_merge_point M2 returns 2.
#
function nearest_common_commit_to_merge_point(){
MERGE_POINT=$1
# Current on the master branch.
# get all parents from merged commit id(HEAD).
parents_commits=`git rev-list --parents -n 1 ${MERGE_POINT}`
#Commits on master branch
common_commit[0]=`git log --pretty=format:"%h" --first-parent ${parents_commits[0]}`
common_commit_arr_1st=(${common_commit[0]//\n/ })
#Find all common commits from HEAD(Merged point).
for first_parents in ${parents_commits}
do
common_commit[1]=`git log --pretty=format:"%h" --first-parent ${first_parents}`
common_commit_arr_2nd=(${common_commit[1]//\n/ })
common_commit_arr_1st=($(comm -12 <(printf '%s\n' "${common_commit_arr_1st[@]}" | LC_ALL=C sort) <(printf '%s\n' "${common_commit_arr_2nd[@]}" | LC_ALL=C sort)))
done
#All we need is the top commit id in common commits.
common_id=${common_commit_arr_1st[0]}
echo ${common_id}
}
#初始化build history环境
#默认在 ~/ 目录下建立 .build_history 文件夹
function init_history(){
cd ~
export history_root="`pwd`/.build_history"
cd -
if [[ ! -d "$history_root" ]]; then
mkdir ${history_root}
fi
}
#写入当前build的commit id戳
# write_path: 历史记录文件路径
# branch_name: 分支名
# commit_id: 要写入的commit id
function write_build_history(){
write_path=$1
branch_name=$2
commit_id=$3
BUILT=`check_if_built ${write_path} ${branch_name}`
contents=${branch_name}:${commit_id}
if [[ ${BUILT} == "Y" ]]; then
sed -i "s/${branch_name}:.*/${contents}/g" ${file_path}
else
echo "${contents}" >> ${write_path}
fi
}
#获取或创建built历史记录
#write_path: 历史记录存放路径
function mk_or_get_file_path(){
write_path=$1
if [[ ! -d "$write_path" ]]; then
mkdir -p $write_path
fi
file_path="${write_path}/last_build"
touch ${file_path}
echo ${file_path}
}
# 检查是否已被buid过
# file_path: 历史记录存放文件路径
# branch_name: 分支名
function check_if_built(){
file_path=$1
branch_name=$2
BUILT="N"
grep ${branch_name} ${file_path} > /dev/null
if [[ $? == 0 ]]; then
BUILT="Y"
fi
echo $BUILT
}
#获取上一次build的commit id
#write_path: 历史记录存放文件夹
#branch_name: 分支名
function get_last_built_commit(){
write_path=$1
branch_name=$2
file_path="`mk_or_get_file_path ${write_path} ${branch_name}`"
last_built_commit_id=`grep -w "${branch_name}" ${file_path} | awk -F ":" '{print $2}'`
#if [[ -z last_built_commit_id ]]; then
# last_built_commit_id="HEAD"
#fi
echo ${last_built_commit_id}
}
#检查目录当前commit是否已经build过,未build返回‘Y’
#module_dir: 目录路径, 该路径会转换为md5值.
function check_if_need_build(){
module_dir=$1
module_dir=`echo -n ${module_dir} | md5sum | cut -d ' ' -f1`
echo ${module_dir}
branch_name=$2
#1. init
init_history
#2. check history
module_history=`mk_or_get_file_path "${history_root}/${module_dir}"`
built=`check_if_built ${module_history} ${branch_name}`
last_built_commit="HEAD"
changed="Y" #default "Y"
if [[ ${built} == "Y" ]]; then
last_built_commit=`get_last_built_commit ${module_history} ${branch_name}`
changed=`differences_check ${last_built_commit} "HEAD" ${module_dir}`
fi
#3. check changed or not
if [[ ${changed} == "Y" ]]; then
echo "Y"
else
echo "N"
fi
}
#将当前的commit id写入历史记录
# module_dir: 目录路径
# branch_name: 分支名
function post_build(){
module_dir=$1
branch_name=$2
commit_id=`git log --pretty=format:"%h" -n 1 ${module_dir}`
module_dir=`echo -n ${module_dir} | md5sum | cut -d ' ' -f1`
module_history=`mk_or_get_file_path ${history_root}/${module_dir}`
write_build_history ${module_history} ${branch_name} ${commit_id}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment