recipe.sh代码分析(下)

 2021SC@SDUSC

recipe.sh代码如下:

#!/bin/bash

require 'styles'

install_recipe() {
    local recipe_file="$1"
    if ! [[ -f "${recipe_file}" ]]; then
        echo $(error 'Recipe not found:') "${recipe_file}"
        exit 1
    fi

    local rx="${package}${recipe:+:${recipe}}"
    echo $(info 'Installing recipe:') $(highlight "${rx}")
    for option in "${recipe_options[@]}"; do
        echo $(info '- option:') $(print_option "${option}")
    done

    check_recipe_info

    apply_download_files

    apply_install_files

    apply_patch_files
}

print_section() {
    local section="$1"
    sed -n '/^'"${section}"':/,/^[^[:space:]#]/ {
        /^[^[:space:]#]/ !p
    }'
}

check_recipe_info() {
    local recipe_decl=$(
        cat "${recipe_file}" |
            print_section 'recipe' |
            grep '^[ ]*Rx: ' |
            sed 's/^[ ]*Rx:[ "'"'"']*\(.*\)[ "'"'"']*$/\1/'
    )
    [[ -z "${recipe}" ]] || [[ "${recipe_decl}" == "${recipe}" ]] || (
        echo $(error 'Invalid recipe:') "'${recipe_decl}' does not match file name '${recipe_file}'"
        exit 1
    )
}

get_filename() {
    local url="$1"
    # if a filename is specified, use it
    if [[ "$url" = *::* ]]; then
        echo "${url%%::*}"
    else
        echo "${url##*/}"
    fi
}

download_file() {
    local url="$1"
    local filename="$(get_filename $url)"
    local check_update=""
    local msg='Downloading file:'

    if [[ -e "${package_dir}/${filename}" ]]; then
        check_update="-z $filename"
        msg='Checking for update of external file:'
    fi
 
    (
        cd "${package_dir}"
        echo $(info "$msg") $(highlight "$filename")
        curl -fRL -o "$filename" $check_update "${url#*::}"
    )
}

apply_download_files() {
    if ! grep -q '^download_files:' "${recipe_file}"; then
        return
    fi
    local file_patterns=(
        $(cat "${recipe_file}" |
            print_section 'download_files' |
            sed '/^[ ]*#/ d; s/^[ ]*-[ ]//'
        )
    )
    if (( ${#file_patterns[@]} == 0 )); then
        return
    fi
    for _item in ${file_patterns[@]}; do
        download_file $_item || (
            echo $(error 'Error:') "failed to download files in recipe ${rx}"
            exit 1
        )
    done
}

apply_install_files() {
    if ! grep -q '^install_files:' "${recipe_file}"; then
        return
    fi
    local file_patterns=(
        $(cat "${recipe_file}" |
            print_section 'install_files' |
            sed '/^[ ]*#/ d; s/^[ ]*-[ ]//'
        )
    )
    if (( ${#file_patterns[@]} == 0 )); then
        return
    fi
    install_files $(
        cd "${package_dir}"
        ls ${file_patterns[@]} ||
            echo $(error 'Error: some files to install are not found.') >&2
    ) || (
        echo $(error 'Error:') "failed to install files in recipe ${rx}"
        exit 1
    )
}

apply_patch_files() {
    if ! grep -q '^patch_files:' "${recipe_file}"; then
        return
    fi
    local script_header="\
#!/bin/bash
source '${script_dir}/bootstrap.sh'
require 'recipe'
output_dir='${output_dir}'
package='${package}'
recipe='${recipe}'
recipe_options=(
    ${recipe_options[*]}
)
eval \${recipe_options[@]}
"
    cat "${recipe_file}" |
        print_section 'patch_files' |
        sed '{
            1 i\
'"$(escape_sed_text <<<"${script_header}")"'
# patch files
            s/^[ ][ ]//
            s/^\([^[:space:]#]*\):\s*$/patch_file \1 <<EOF/
            2,$ {
                /<<EOF/ i\
EOF
            }
            $ a\
EOF
        }' | bash || (
        echo $(error 'Error:') "failed to patch files in recipe ${rx}"
        exit 1
    )
}

escape_sed_text() {
    sed -e 's/[\\ ]/\\&/g; s/$/\\/'
}

patch_file() {
    local file_name="$1"
    echo $(info 'Patching:') $(print_item "${file_name}")
    local target_file="${output_dir:-.}/${file_name}"
    if ! [[ -e "${target_file}" ]] || ! grep -q '^__patch:$' "${target_file}"; then
        echo '__patch:' >> "${target_file}"
    fi
    local option_list="${recipe_options[*]}"
    local rx="${package}:${recipe}:${option_list// /,}"
    if grep -Fq "# Rx: ${rx}" "${target_file}"; then
        echo $(info 'Updating patch.')
        # first remove the existing patch
        sed '/^# Rx: '"${rx//\//\\/}"' {$/,/^# }$/ d' \
            "${target_file}" > "${target_file}.new" &&
            mv "${target_file}.new" "${target_file}"
    fi
    # read patch contents from standard input
    local patch_contents="$(escape_sed_text)"
    sed -E '
        /^__patch:$/,/^[^[:space:]#]/ {
            $ {
                /^__patch:|^[[:space:]#]/ {
                    a\
# Rx: '"${rx}"' {\
'"${patch_contents}"'
# }
                    q
                }
                i\
# Rx: '"${rx}"' {\
'"${patch_contents}"'
# }
            }
        }
    ' "${target_file}" > "${target_file}.new" &&
    mv "${target_file}.new" "${target_file}" || (
        echo $(error 'Error patching:') "${file_name}"
        exit 1
    )
}

provide 'recipe'

之前讲到download_file函数部分。接下来看apply_download_files函数。这个函数是用来申请下载的。通过grep命令过滤,保证文件是可下载的。为file_patterns赋值,通过sed处理。来保证文件模式的正确。

在apply_install_files函数中,同样通过grep函数保证文件是可下载的。通过sed处理后保证文件下载模式的正确性。然后调用install_files函数。参数自定义。将路径定位到包目录下。即${package_dir}。打开文件模式下的所有文件。

而apply_patch_files和patch_files函数则主要是为使用补丁文件而创建的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值