#!/bin/bash # set -x source ./log_helpers source ./general_utils # if [ ${git_helpers_sourced:-1} = "1" ]; then # readonly git_helpers_sourced=${BASH_SOURCE[0]} readonly repository_already_up_to_date=2 # exec_git_command () { local func="${FUNCNAME[0]}" log_debug "$func:${LINENO} exec-ing [$*]" local __git_result=$(exec_process_substitution $*) log_debug "$func:${LINENO} result=$__git_result" printf '%s' "$__git_result" } # latest_commit () { local func="${FUNCNAME[0]}" # git reflog -> 46c5896 HEAD@{0}: commit: Made update_helpers executable local c=$(git reflog | grep "HEAD@{0}" | cut -d" " -f1) if ! [ -z "$c" ]; then if grep -qE "^[[:xdigit:]]{6,}$" <<< $c; then log_debug "$func:${LINENO} commit -> $c" printf "%s\n" "$c" else log_crit "$func:${LINENO} wrong format for commit c=$c" fi else log_crit "$func:${LINENO} 'git reflog' result empty" fi } # fallback if something went wrong: revert to last valid commit revert_to_commit_before_pull () { local func="${FUNCNAME[0]}" if ! [ -z "$commit_before_pull" ]; then if grep -qE "^[[:xdigit:]]{6,}$" <<< $commit_before_pull; then `git reset --hard "$commit_before_pull"` if [ $? -eq 0 ]; then log_info "$func: git reset --hard $commit_before_pull" return 0 fi log_crit "$func: 'git reset --hard $commit_before_pull' failed!" fi log_crit "$func: wrong format for commit_before_pull" fi log_crit "$func: empty commit_before_pull" return 1 } # revert_to_commit_before_pull git_branch () { # always relative to a git repository echo $(git branch -a | grep '*' | awk '{ print $2 }') } git_customer_branch () { if cd_customer_repository; then customer_branch=$(git_branch) cd_home; echo $customer_branch fi } # clone the customer repository in ./workspace. # this is done only once. # # Cloning into 'customer_281'... # remote: Enumerating objects: 1087, done. # remote: Counting objects: 100% (1087/1087), done. # remote: Compressing objects: 100% (946/946), done. # remote: Total 1087 (delta 404), reused 0 (delta 0), pack-reused 0 # Receiving objects: 100% (1087/1087), 103.27 KiB | 873.00 KiB/s, done. # Resoving deltas: 100% (410/410), done. # clone_customer_repository () { local func="${FUNCNAME[0]}" if [ "$PWD" != "$WORKING_DIRECTORY" ]; then log_fatal "$func:${LINENO} PD != WD ($PWD != $WORKING_DIRECTORY)" fi mkdir -p "./$WORKSPACE_DIR" # check if the directory is empty. If so, clone the # customer repository if ! find ./$WORKSPACE_DIR -mindepth 1 -maxdepth 1 | read; then log_info "$func:${LINENO} cloning ${1} into ${PWD}/${WORKSPACE_DIR}..." if ! cd "./$WORKSPACE_DIR"; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not change to $WORKSPACE_DIR" fi if ! exec_git_command git clone "$1"; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not clone $1" fi ########################## CLONING DONE ############################ log_debug "$func:${LINENO} cloning ${1} done" # after cloning, cd into repository, and re-initialize, # setting the work-tree as "/". This has the effect that # a "git pull" will automatically fetched files in the # corresponding sytem-folders. ####################### CD INTO REPOSITORY ########################## if ! cd ${CUSTOMER_ID_BASE_DIR}; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not change to $CUSTOMER_ID_BASE_DIR" fi log_debug "$func:${LINENO} cd into $CUSTOMER_ID_BASE_DIR" ##################### CONFIGURE HOOKS DIRECTORY ###################### if ! exec_git_command git config core.hooksPath .githooks; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not configure hooks directory" fi ###################### CHECKOUT LOCAL BRANCH ######################### if ! exec_git_command git checkout "$LOCAL_BRANCH"; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not checkout $LOCAL_BRANCH" fi log_debug "$func:${LINENO} checked out local branch $LOCAL_BRANCH" ######################## CONFIGURE WORKTREE ########################## if ! exec_git_command git config core.worktree "/"; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not configure worktree '/'" fi log_debug "$func:${LINENO} configured worktree '/'" ########################### FETCH ALL ################################# if ! exec_git_command git fetch --all; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} can not fetch --all for $LOCAL_BRANCH" fi log_debug "$func:${LINENO} fetch repository" ########################## RE-INIT REPOSITORY ######################## if ! exec_git_command git reset --hard "$LOCAL_BRANCH"; then update_psa_clone_error # message to ISMAS log_fatal "$func:${LINENO} re-init of $LOCAL_BRANCH failed" fi log_debug "$func:${LINENO} reset --hard $LOCAL_BRANCH" INITIAL_CLONE=true log_debug "$func:${LINENO} re-init of ${1} done" update_psa_clone_customer_repository else # the directory is not empty, so we assume the # customer-repository has been cloned already if ! [[ -d "./${WORKSPACE_DIR}/$CUSTOMER_ID" ]]; then log_fatal "$func:${LINENO} $PWD $WORKSPACE_DIR/$CUSTOMER_ID"\ "wrong repository: $(ls -d './${WORKSPACE_DIR}/*')" fi local __m="./${WORKSPACE_DIR}/$CUSTOMER_ID exists" log_info "$func:${LINENO} $__m, no clone necessary" fi cd_home log_info "$func:${LINENO} nach cd_home $PWD" } # clone_customer_repository -> # https://git.mimbach49.de/GerhardHoffmann/customer_281.git cd_customer_repository () { local func="${FUNCNAME[0]}" if [ "$PWD" != "$WORKING_DIRECTORY" ]; then log_fatal "$func:${LINENO} PD != WD ($PWD != $WORKING_DIRECTORY)" fi if ! [[ -d "$CUSTOMER_ID_BASE_DIR" ]]; then log_fatal "$func:${LINENO}: $CUSTOMER_ID_BASE_DIR does not exist!" fi if ! cd "$CUSTOMER_ID_BASE_DIR"; then log_fatal "$func:${LINENO}: cannot cd to $CUSTOMER_ID_BASE_DIR !!!" fi log_debug "$func:${LINENO}: cd to $CUSTOMER_ID_BASE_DIR" return 0 } cd_home () { if cd "$WORKING_DIRECTORY" &>/dev/null ; then return 0 fi return 1 } pull_customer_repository () { local func="${FUNCNAME[0]}" if ! cd_customer_repository; then return 1 fi log_crit "$func:${LINENO}: executing 'git pull'..." exec_git_command 'git pull' # GIT_UPDATE_LOG updated by hook post-merge. it contains the names of the # changed files or opkg-commands to execute. # If 'git pull' has fetched new data, then there are lines starting with # DOWNLOAD or EXECUTE. if grep -qE "^[[:space:]]*(DOWNLOAD|EXECUTE)" "$GIT_UPDATE_LOG"; then log_info "$func:${LINENO}: new data fetched from repository" cd_home; return 0 fi log_warn "$func:${LINENO}: no data fetched from repository" cd_home; return 1 } # pull_customer_repository customer_281 changed_file_names () { local func="${FUNCNAME[0]}" if cd_customer_repository ; then local git_res=$(exec_git_command 'git diff --stat master@{1} master') git_res=${git_res//[$'\r\n\t']/ } log_debug "$func:${LINENO}: git_res=$git_res" local file_names="" for f in ${KNOWN_FILES[@]} ; do if grep -qE "${f}" <<< "$git_res"; then if ! [ -z $file_names ]; then file_names="$f $file_names" else file_names="$f" fi log_debug "$func:${LINENO}: $f found in $git_res" fi done cd_home; log_debug "$func:${LINENO}: file_names=$file_names" ; printf '%s' "$file_names" else log_crit "$func:${LINENO}: cannot cd to $customer_repository "\ "while in $PWD" fi } get_blob () { # get the blob of the file(name) passed as $1 # note: this can be used for any file in the filesystem echo $(git hash-object $1) } get_commit_for_blob () { blob=$(get_blob $1) if [ ! -z $blob ]; then # search for the blob in all commits for the file(name) $1 echo $(echo $(git log --all --pretty=format:%H -- $1) | xargs -I{} sh -c "git ls-tree {} -- $1 | grep -q $blob && echo {}") fi }