install-packages.sh代码解析

2021SC@SDUSC

install-package.sh从名字来看是安装各种包的。其代码如下:

#!/bin/bash

script_dir="$(dirname "$0")"
target="$1"
output_dir="$2"

option_no_update="${no_update:+1}"

source "${script_dir}"/bootstrap.sh
require 'styles'
require 'resolver'

if [[ -z "$target" ]] || [[ -z "$output_dir" ]]; then
    echo "Usage: $(basename "$0") :<configuration>|<package-name> <output-directory>"
    exit 1
fi

set -e

[[ -d "${output_dir}" ]] || mkdir -p "${output_dir}"

files_updated=0

install_package() {
    local user_name="$(resolve_user_name "$1")"
    local package_name="$(resolve_package_name "$1")"
    local package_dir="${root_dir:-.}/package/${user_name}/${package_name}"

    local package="$(resolve_package "$1")"
    local branch="$(resolve_branch "$1")"
    local branch_label="${branch:+@${branch}}"

    local recipe="$(resolve_recipe "$1")"
    local recipe_options=($(resolve_recipe_options "$1"))

    fetch_or_update_package

    if [[ -n "${recipe}" ]]; then
        require 'recipe'
        install_recipe "${package_dir}/${recipe}.recipe.yaml"
    elif [[ -f "${package_dir}/recipe.yaml" ]]; then
        require 'recipe'
        install_recipe "${package_dir}/recipe.yaml"
    else
        install_files_from_package "${package_dir}"
    fi
}

fetch_or_update_package() {
    if ! [[ -d "${package_dir}" ]]; then
        echo $(info 'Downloading package:') $(highlight "${package}") $(print_option "${branch_label}")
        local fetch_options=()
        if [[ -n "${branch}" ]]; then
            fetch_options+=(--branch "${branch}")
        fi
        "${script_dir}"/fetch-package.sh "${package}" "${package_dir}" "${fetch_options[@]}"
    else
        if [[ -z "${option_no_update}" ]]; then
            echo $(info 'Updating package:') $(highlight "${package}")
        else
            echo $(info 'Found package:') $(highlight "${package}")
        fi
        "${script_dir}"/update-package.sh "${package_dir}" "${branch}"
    fi
}

install_files_from_package() {
    local package_dir="$1"
    local IFS=$'\r\n'
    local data_files=(
        $(
            cd "${package_dir}"
            ls *.yaml 2> /dev/null \
                | grep -v -e '\.custom\.yaml$' -e '\.recipe\.yaml$' -e '^recipe\.yaml$'
            ls *.txt 2> /dev/null
            ls *.gram 2> /dev/null
            ls opencc/*.* 2> /dev/null \
                | grep -e '\.json$' -e '\.ocd$' -e '\.txt$'
        )
    )
    install_files "${data_files[@]}"
}

install_files() {
    if [[ "$#" -eq 0 ]]; then
        return
    fi
    local source_path
    local target_path
    for file in "$@"; do
        source_path="${package_dir}/${file}"
        target_path="${output_dir}/${file}"
        if ! [ -e "${target_path}" ]; then
            create_containing_directory "${target_path}"
            echo $(info 'Installing:') $(print_item "${file}")
        elif ! diff -q "${source_path}" "${target_path}" &> /dev/null; then
            echo $(info 'Updating:') $(print_item "${file}")
        else
            continue
        fi
        cp "${source_path}" "${target_path}"
        ((++files_updated))
    done
}

create_containing_directory() {
    local target_dir="$(dirname "$1")"
    if ! [ -d "${target_dir}" ]; then
        echo $(info 'Creating directory:') $(print_item "${target_dir}")
        mkdir -p "${target_dir}"
    fi
}

load_package_list_from_target "${target}"

for package in "${package_list[@]}"; do
    install_package "${package}"
done

if [[ "${files_updated}" -eq 0 ]]; then
    echo $(print_result 'No files updated.')
else
    echo $(print_result "Updated ~ ${files_updated} files " \
                        "from ${#package_list[@]} packages in") "'${output_dir}'"
fi

第一行给脚本目录赋值为 dirname加脚本名称。target赋值为第一个参数。输出的目录为第二个参数。然后是没见过的echo中出现了冒号加一。网上没找到相关资料。然后去shell上自己试:

这样赋的值是不管update是多少,最后都只跟冒号后的数有关。也就是说这里option_no_update被直接赋值为1了。

然后创建一个文件。调用require函数(详见bootstrap.sh,用来引导模块的函数,在其中会创建与该名称相关的.sh文件),将styles和resolver作为参数导入。

然后判断target和output_dir的值是否为零,为零报一个输出然后异常状态退出。

set -e 当脚本执行出现意料之外的情况时,立即退出,避免错误被忽略,导致最终结果不正确。

接下来判断output_dir是否已经为一个目录文件名,是的话,将file_dated的值赋为零;如果不是,则创建一个父目录。

进入install_package函数,前面是几个本地变量的赋值。然后引入fetch_or_update_package函数。如果recipe的值不为零,建一个recipe模板,调用本函数,参数为recipe "${package_dir}/${recipe}.recipe.yaml"。如果${package_dir}/recipe.yaml为一个普通文件。引入recipe模板,调用本函数,参数为recipe "${package_dir}/recipe.yaml"。否则调用install_files_from_package,参数为${package_dir};

fetch_or_update_package函数主要是用来选择接受或者更新包的。

进入install_files_from_package函数。前面同样是赋值。将路径锁定到package_dir下。将.yaml所有文件的错误输出定向到/dev/null文件中,即&1。后面是grep的相关匹配模式。.txt,.gram,opencc/.都重定向到&1中。

引入install_files函数,参数为data_files数组的所有元素。

install_files主要用来安装文件,create_containing_directory则是用来创建目录将所有文件放入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值