# SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) # Handler for git # Usage (in package.mk): # PKG_URL (mandatory) must point to a git repository (git://... or https://example.com/repo.git) # PKG_VERSION (mandatory) must point to a commit SHA, e.g. a1b2c3d # PKG_GIT_SHA (optional) full hash of git commit # PKG_GIT_CLONE_BRANCH (optional) clone specific branch # PKG_GIT_CLONE_SINGLE (optional) clone single branch only (set to yes) # PKG_GIT_CLONE_DEPTH (optional) history to clone, must be a number # PKG_GIT_SUBMODULE_DEPTH (optional) history of submodules to clone, must be a number _get_repo_already_downloaded() { if [ -d "${PACKAGE}" ]; then ( cd "${PACKAGE}" _get_repo_clean [ -n "$(git ls-remote . | grep -m1 HEAD | awk "/^${PKG_VERSION}/ {print \$1;}")" ] || die "ERROR: ${PACKAGE}: failed to determine git HEAD" [ "${PKG_URL}" = "$(git remote get-url origin)" ] || die "ERROR: ${PACKAGE}: failed to obtain URL of origin" [ -z "${PKG_GIT_CLONE_BRANCH}" ] && exit 0 [ "${PKG_GIT_CLONE_BRANCH}" = "$(git branch | grep ^\* | cut -d ' ' -f2)" ] || die "ERROR: ${PACKAGE}: failed to determine current git branch" exit 0 ) return else return 1 fi } _get_repo_clean() { git clean -fdx git checkout -- . } # Latest file already present, exit now... _get_repo_already_downloaded && exit 0 lock_source_dir "${1}" # Check again in case of concurrent access - if nothing needs to be downloaded, exit now... _get_repo_already_downloaded && exit 0 # At this point, we need to download something... build_msg "CLR_GET" "GET" "${1} (git)" "indent" pkg_lock_status "GETPKG" "${PKG_NAME}" "unpack" "processing package repository..." rm -f "${STAMP_URL}" "${STAMP_SHA}" GIT_CLONE_PARAMS="--recursive" GIT_SUBMODULE_PARAMS="" [ -n "${PKG_GIT_CLONE_BRANCH}" ] && GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --branch ${PKG_GIT_CLONE_BRANCH}" [ "${PKG_GIT_CLONE_SINGLE}" = "yes" ] && GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --single-branch" if [ -n "${PKG_GIT_CLONE_DEPTH}" ]; then if [[ "${PKG_GIT_CLONE_DEPTH}" =~ ^[0-9]+$ ]]; then GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --depth ${PKG_GIT_CLONE_DEPTH}" else die "ERROR: PKG_GIT_CLONE_DEPTH is not a number! (${PKG_GIT_CLONE_DEPTH})" fi fi if [ -n "${PKG_GIT_SUBMODULE_DEPTH}" ]; then if [[ "${PKG_GIT_SUBMODULE_DEPTH}" =~ ^[0-9]+$ ]]; then GIT_SUBMODULE_PARAMS="${GIT_SUBMODULE_PARAMS} --depth ${PKG_GIT_SUBMODULE_DEPTH}" else die "ERROR: PKG_GIT_SUBMODULE_DEPTH is not a number! (${PKG_GIT_SUBMODULE_DEPTH})" fi fi GIT_FOUND="no" opwd="$(pwd)" for d in "${SOURCES}/${1}/${1}-"* ; do if [ -d "${d}/.git" ]; then if [ "${GIT_FOUND}" = "no" ]; then cd "${d}" if [ "${PKG_URL}" = "$(git remote get-url origin)" ]; then if [[ -z "${PKG_GIT_CLONE_BRANCH}" ]] || [[ $(git branch | grep "^\* ${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]]; then GIT_FOUND="yes" GIT_DIR="${d}" _get_repo_clean elif [ $(git branch | grep "^ ${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]; then GIT_FOUND="yes" GIT_DIR="${d}" _get_repo_clean git checkout "${PKG_GIT_CLONE_BRANCH}" elif [ $(git branch -a | grep "^ remotes/origin/${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]; then GIT_FOUND="yes" GIT_DIR="${d}" _get_repo_clean git checkout -b "${PKG_GIT_CLONE_BRANCH}" "origin/${PKG_GIT_CLONE_BRANCH}" else build_msg "CLR_CLEAN" "DELETE" "(${d})" cd "${opwd}" rm -rf "${d}" fi if [ "${GIT_FOUND}" = "yes" ]; then build_msg "CLR_GET" "GIT PULL" "${1}" # If there is an error with 'git pull' or updating the submodules, just reclone # NOTE: we run the submodule update twice if the clone already # exists - but deduplicating would complicate the logic quite a lot and # the second time is almost a no-op if ! git pull || ! git submodule update --init --recursive ${GIT_SUBMODULE_PARAMS}; then cd "${opwd}" build_msg "CLR_CLEAN" "DELETE" "(${d})" GIT_FOUND=NO rm -rf "${d}" fi cd "${opwd}" fi else build_msg "CLR_CLEAN" "DELETE" "(${d})" cd "${opwd}" rm -rf "${d}" fi fi else build_msg "CLR_CLEAN" "DELETE" "(${d})" rm -rf "${d}" fi done cd "${opwd}" if [ "${GIT_FOUND}" = "no" ]; then build_msg "CLR_GET" "GIT CLONE" "${1}" git clone ${GIT_CLONE_PARAMS} "${PKG_URL}" "${PACKAGE}" elif [ ! "${GIT_DIR}" = "${PACKAGE}" ]; then mv "${GIT_DIR}" "${PACKAGE}" fi ( cd "${PACKAGE}" [ $(git log --oneline --pretty=tformat:"%H" | grep "^${PKG_VERSION}" | wc -l) -eq 1 ] || die "There is no commit '${PKG_VERSION}' on branch '$(git branch | grep ^\* | cut -d ' ' -f2)' of package '${1}'! Aborting!" git reset --hard "${PKG_VERSION}" build_msg "CLR_GET" "GIT SUBMODULE" "${1}" git submodule update --init --recursive ${GIT_SUBMODULE_PARAMS} ) GIT_SHA="$(git ls-remote "${PACKAGE}" | grep -m1 HEAD | awk '{print $1;}')" if [ -n "${PKG_GIT_SHA}" -a "${PKG_GIT_SHA}" != "${GIT_SHA}" ]; then build_msg "CLR_WARNING" "WARNING" "Incorrect git hash in repository: got ${GIT_SHA}, wanted ${PKG_GIT_SHA}" fi