265 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/bash
 | 
						|
# set -x 
 | 
						|
 | 
						|
# if [ ${git_helpers_sourced:-1} = "1" ]; then
 | 
						|
#    readonly git_helpers_sourced=${BASH_SOURCE[0]}
 | 
						|
#else
 | 
						|
#    return 0
 | 
						|
#fi
 | 
						|
 | 
						|
 | 
						|
# source ./log_helpers
 | 
						|
 | 
						|
readonly GIT_SSL_NO_VERIFY=true
 | 
						|
readonly repository_already_up_to_date=2
 | 
						|
 | 
						|
#
 | 
						|
exec_git_command () {
 | 
						|
    local func="${FUNCNAME[0]}"
 | 
						|
    
 | 
						|
    log_debug "$func:${LINENO} exec-ing [$*]"
 | 
						|
 | 
						|
    exec {fd}< <($@)
 | 
						|
    local ps_pid=$!             # remember pid of process substitution
 | 
						|
 | 
						|
    local git_result=""
 | 
						|
    while read t <&$fd; do
 | 
						|
        if ! [ -z "$t" ]; then
 | 
						|
            git_result="${git_result}$t"
 | 
						|
        fi
 | 
						|
    done
 | 
						|
        
 | 
						|
    exec {fd}>&-                # close fd (i.e. process substitution)
 | 
						|
    wait $ps_pid                # wait for the subshell to finish
 | 
						|
 | 
						|
    git_result=$(printf "$git_result" | tr '\n' ' ')
 | 
						|
    printf "%s\n" $git_result
 | 
						|
}
 | 
						|
 | 
						|
# 
 | 
						|
latest_commit () {
 | 
						|
    local func="${FUNCNAME[0]}"
 | 
						|
    # git reflog -> 46c5896 HEAD@{0}: commit: Made update_helpers.sh 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
 | 
						|
 | 
						|
# clone the customer repository in ./UpdateController/workspace.
 | 
						|
# this is done only once.
 | 
						|
clone_customer_repository () {
 | 
						|
    local func="${FUNCNAME[0]}"
 | 
						|
    current_dir=${PWD##*/}
 | 
						|
    current_dir="./${current_dir:-/}"
 | 
						|
    if [ "$current_dir" = "./UpdateController" ]; then
 | 
						|
        if ! [[ -d ./workspace ]]; then
 | 
						|
            { mkdir -p ./workspace; }
 | 
						|
        fi
 | 
						|
        # check if the directory is empty. If so, clone the
 | 
						|
        # customer repository
 | 
						|
        if ! find ./workspace -mindepth 1 -maxdepth 1 | read; then
 | 
						|
            log_debug "$func:${LINENO} cloning ${1} ..."
 | 
						|
            if { cd ./workspace ; }; then
 | 
						|
                $(exec_git_command git clone "$1")
 | 
						|
                if [ $? -eq 0 ]; then
 | 
						|
                    log_debug "$func:${LINENO} cloning ${1} done"
 | 
						|
                    cd - ; return 0
 | 
						|
                fi
 | 
						|
                cd -
 | 
						|
            fi
 | 
						|
        else
 | 
						|
            # the directory is not empty, so we assume the customer-repository
 | 
						|
            # has been cloned alread
 | 
						|
            if ! [[ -d ./workspace/$customer_id ]]; then
 | 
						|
                local m="wrong repository: $(ls -d './workspace/*')"
 | 
						|
                log_fatal "$func:${LINENO} $m"
 | 
						|
            else
 | 
						|
                return 0
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
    return 1
 | 
						|
}
 | 
						|
# clone_customer_repository ->
 | 
						|
# https://git.mimbach49.de/GerhardHoffmann/customer_281.git
 | 
						|
 | 
						|
cd_customer_repository () {
 | 
						|
    # has to be called in ./UpdateController
 | 
						|
    local func="${FUNCNAME[0]}"
 | 
						|
    current_dir=${PWD##*/}
 | 
						|
    current_dir="./${current_dir:-/}"
 | 
						|
    if [ "$current_dir" = "./UpdateController" ]; then
 | 
						|
        repository_dir="./workspace/${customer_id}"
 | 
						|
        if ! [[ -d "$repository_dir" ]]; then
 | 
						|
            log_crit "$func:${LINENO}: $repository_dir does not exist!"
 | 
						|
            return 1
 | 
						|
        fi
 | 
						|
        
 | 
						|
        if ! { cd $repository_dir; } ; then
 | 
						|
            log_crit "$func:${LINENO}: cannot change to $repository_dir!"
 | 
						|
            return 1
 | 
						|
        fi
 | 
						|
 | 
						|
        log_debug "$func:${LINENO}: cd to $repository_dir!"
 | 
						|
        return 0
 | 
						|
    fi
 | 
						|
    return 1
 | 
						|
}
 | 
						|
 | 
						|
cd_home () {
 | 
						|
    if cd - &>/dev/null ; then
 | 
						|
        return 0
 | 
						|
    fi
 | 
						|
    return 1
 | 
						|
}
 | 
						|
 | 
						|
pull_customer_repository () {
 | 
						|
    # has to be called in ./UpdateController
 | 
						|
    local func="${FUNCNAME[0]}"
 | 
						|
 | 
						|
    if ! cd_customer_repository ; then
 | 
						|
        return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    local commit_before_pull=$(latest_commit)
 | 
						|
    if [ -z $commit_before_pull ]; then
 | 
						|
        cd_home ; return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    log_debug "$func:${LINENO}: commit_before_pull=$commit_before_pull"
 | 
						|
    
 | 
						|
    local git_result=$(exec_git_command 'git pull')
 | 
						|
 | 
						|
    if [ -z "$git_result" ]; then
 | 
						|
        log_warn "$func:${LINENO}: git result empty" ; cd_home;
 | 
						|
        return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    # see 'man -Pless\ +/parameter/pattern/string/bash'
 | 
						|
    git_result=${git_result//[$'\r\n\t']/ }
 | 
						|
 | 
						|
    log_debug "$func:${LINENO} git-pull-result=${git_result}"
 | 
						|
 | 
						|
    if grep -qE "^Already\s+\up\s+\to\s+date.*$" <<< $git_result; then
 | 
						|
        log_warn "$func:${LINENO}: repository $PWD already up to date."
 | 
						|
        read $1 <<< 'yes'
 | 
						|
        cd_home ; return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    local commit_after_pull=$(latest_commit)
 | 
						|
    if [ -z $commit_after_pull ]; then
 | 
						|
        cd_home ; return 1
 | 
						|
    fi
 | 
						|
    
 | 
						|
    log_debug "$func:${LINENO}: commit_after_pull=$commit_after_pull"
 | 
						|
 | 
						|
    # Note: # 'git pull' is a 'git fetch' followed by a 'git merge'.
 | 
						|
    # Here's the fetch portion:
 | 
						|
    #
 | 
						|
    # remote: Counting objects: 11, done.
 | 
						|
    # remote: Compressing objects: 100% (5/5), done.
 | 
						|
    # remote: Total 7 (delta 2), reused 0 (delta 0)
 | 
						|
    #
 | 
						|
    # At this point, you've told the remote what you want.
 | 
						|
    # It finds all the objects it needs to give you,
 | 
						|
    # compresses them for faster transfer over the network,
 | 
						|
    # and then reports what it's sending you.
 | 
						|
    # 
 | 
						|
    # Unpacking objects: 100% (7/7), done.
 | 
						|
    # 
 | 
						|
    # You receive the pack (set of compressed objects) and unpack it.
 | 
						|
    #
 | 
						|
    # From ssh://my.remote.host.com/~/git/myproject
 | 
						|
    # * branch            master     -> FETCH_HEAD
 | 
						|
 | 
						|
    # You've fetched the branch 'master' from the given remote;
 | 
						|
    # the ref FETCH_HEAD now points to it.
 | 
						|
    # Now we move on to the merge - precisely, git will merge
 | 
						|
    # FETCH_HEAD (the remote's master branch) into your current branch
 | 
						|
    # (presumably master).
 | 
						|
    #
 | 
						|
    #######################################################################
 | 
						|
    # here starts "message"
 | 
						|
    # 
 | 
						|
    # Updating 9d447d2..f74fb21
 | 
						|
    # Fast forward
 | 
						|
    #
 | 
						|
    # It turns out that you haven't diverged from the remote's master branch,
 | 
						|
    # so the merge is a fast-forward (a trivial merge where it simply moves
 | 
						|
    # you forward in the history).
 | 
						|
    #
 | 
						|
    # Git notes the original position of your master branch (9d447d2)
 | 
						|
    # and the new position (f74fb21) it's been fast-forwarded to.
 | 
						|
    # If you had diverged from the remote's master branch,
 | 
						|
    # you'd see the output of a recursive merge here - Merge made
 | 
						|
    # by recursive, possibly along with some Auto-merged <file>
 | 
						|
    # and (oh no!) merge conflicts!
 | 
						|
    #
 | 
						|
    # szeged/1/1/etc/psa_config/device.conf | 13 +++++++------
 | 
						|
    # szeged/update.conf                    |  2 +-
 | 
						|
    # 2 files changed, 8 insertions(+), 7 deletions(-)
 | 
						|
    #  
 | 
						|
    # Finally, it shows you the diffstat between the original and post-merge
 | 
						|
    # position of your master branch;
 | 
						|
    # this is basically what you'd get from
 | 
						|
    #
 | 
						|
    # git diff --stat master@{1} master.
 | 
						|
    # 
 | 
						|
 | 
						|
    update_commit="${commit_before_pull}..${commit_after_pull}"
 | 
						|
    if ! grep -qE ".*Updating\s+${update_commit}.*?" <<< $git_result; then
 | 
						|
        log_crit "$func:${LINENO}: no $update_commit in [ $git_result ]"
 | 
						|
        cd_home ; return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    cd_home ; return 0
 | 
						|
}
 | 
						|
# 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 'update.conf' 'opkg_commands' ; do 
 | 
						|
            if grep -qE ".*${f}.*?" <<< $git_res; then
 | 
						|
                file_names="$f $file_names"
 | 
						|
            fi
 | 
						|
        done    
 | 
						|
 | 
						|
        cd_home ; printf "$file_names"
 | 
						|
    else
 | 
						|
        log_crit "$func:${LINENO}: cannot cd to $customer_repository "\
 | 
						|
            "while in $PWD"
 | 
						|
    fi
 | 
						|
}
 |