SettingsLib/fetch.sh
#!/bin/bash

# Exit on error
set -e

declare -r SCRIPTNAME=${BASH_SOURCE[0]}
declare -r SHORT_OPTS=u:,t:
declare -r LONG_OPTS=set-repo-url:,set-repo-tag:,get-repo-url,get-repo-tag,apply-patches-only
declare -r FWB_DIR='fwb'
declare REPO_URL='https://android.googlesource.com/platform/frameworks/base.git'
declare REPO_TAG='android-16.0.0_r1'
declare -a LIBS=(
    'BannerMessagePreference'
    'ButtonPreference'
    'CollapsingToolbarBaseActivity'
    'LayoutPreference'
    'SettingsTheme'
    'TwoTargetPreference'
)

function main() {
    while true; do
        case "$1" in
            --get-repo-url) echo "$REPO_URL"; exit 0;;
            --get-repo-tag) echo "$REPO_TAG"; exit 0;;
            --apply-patches-only) git-fwb stash && apply_patches; exit $?;;
            -u|--set-repo-url)
                REPO_URL="${2-}"
                shift 2
                ;;
            -t|--set-repo-tag)
                REPO_TAG="${2-}"
                shift 2
                ;;
            --) shift; break;;
            *) echo "Unexpected option: $1"; exit 1
        esac
    done

    if [ $# -gt 0 ]; then
        declare -a LIBS=("$@")
    fi

    echo "Preparing the repo..."
    echo "  URL: $REPO_URL"
    echo "  Branch/Tag: $REPO_TAG"
    if [ "$(cd $FWB_DIR 2>/dev/null && git rev-parse --is-inside-work-tree 2>/dev/null)" != 'true' ] || # repo doesn't exist
        [ "$(git-fwb config --get remote.origin.url 2>/dev/null)" != "$REPO_URL" ] || # repo URL diverged
        [ "$(git-fwb describe --match="$REPO_TAG" 2>/dev/null)" != "$REPO_TAG" ]; then # repo tag/branch diverged
        rm -rf $FWB_DIR
        git clone --depth=1 --filter=blob:none --no-checkout --single-branch --branch "$REPO_TAG" \
            "$REPO_URL" $FWB_DIR
    else
        echo '  The repo has not diverged!'
        if ! git-fwb diff --exit-code >/dev/null; then
            git-fwb stash
        fi
    fi

    echo 'Initializing sparse fetch...'
    git-fwb sparse-checkout set --no-cone
    local lib target
    for lib in "${LIBS[@]}"; do
        target=packages/SettingsLib/"$lib"
        echo "  + $lib"
        git-fwb sparse-checkout add "$target"
    done
    git-fwb checkout

    echo 'Verifying integrity...'
    for lib in "${LIBS[@]}"; do
        target=packages/SettingsLib/"$lib"
        echo -n "  ${lib} ... "
        # The lib is only valid if it's shipped with a Soong configuration file
        if ! git-fwb ls-files --error-unmatch "$target"/Android.bp >/dev/null; then
            # Print what's inside and abort
            git-fwb ls-files --error-unmatch "$target"
            exit 1
        fi
        echo 'OK!'
    done

    apply_patches || exit $?

    echo 'Done.'
}

function apply_patches() {
    if [ -d patches ]; then
        local -a patches=(patches/*.patch)
        if [ -f "${patches[0]-}" ]; then
            echo "Applying ${#patches[@]} patches..."
            git -C $FWB_DIR apply --verbose "${patches[@]/#/../}" || return $?
            echo 'OK!'
        fi
    fi
}

function git-fwb() {
    git --git-dir=$FWB_DIR/.git --work-tree=$FWB_DIR "$@"
}

if ! OPTS=$(getopt --alternative --name "$SCRIPTNAME" \
    --options $SHORT_OPTS --longoptions $LONG_OPTS -- "$@"); then
    echo "Usage: $SCRIPTNAME [-u <url>|--set-repo-url=<url>] [-t <tag>|--set-repo-tag=<tag>] " \
        "[--get-repo-url] [--get-repo-tag] [--apply-patches-only] [lib ...]"
    exit 1
fi
eval set -- "$OPTS"

(
    # Before starting, CWD to where this script is
    cd -P -- "$(dirname -- "$SCRIPTNAME")"
    main "$@"
)
