From 2e0746707de9314853e0a659af396fad9fcb02d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 20 Apr 2023 23:25:04 +0200 Subject: [PATCH] Allow to checkout tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeCheckout.sh | 62 +++++++++++------------ advanced/Scripts/update.sh | 34 +++++++++---- automated install/basic-install.sh | 81 +++++++++++++++++++++--------- 3 files changed, 110 insertions(+), 67 deletions(-) diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index cf57800c..08f9615a 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -18,15 +18,11 @@ source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # is_repo() sourced from basic-install.sh # setupVars set in basic-install.sh # check_download_exists sourced from basic-install.sh -# fully_fetch_repo sourced from basic-install.sh -# get_available_branches sourced from basic-install.sh -# fetch_checkout_pull_branch sourced from basic-install.sh -# checkout_pull_branch sourced from basic-install.sh source "${setupVars}" warning1() { - echo " Please note that changing branches severely alters your Pi-hole subsystems" + echo " Please note that changing branches or tags severely alters your Pi-hole subsystems" echo " Features that work on the master branch, may not on a development branch" echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}" read -r -p " Have you read and understood this? [y/N] " response @@ -36,15 +32,15 @@ warning1() { return 0 ;; *) - echo -e "\\n ${INFO} Branch change has been canceled" + echo -e "\\n ${INFO} Branch/Tag change has been canceled" return 1 ;; esac } checkout() { - local corebranches - local webbranches + local corerefs + local webrefs # Check if FTL is installed - do this early on as FTL is a hard dependency for Pi-hole local funcOutput @@ -111,59 +107,59 @@ checkout() { echo "master" > /etc/pihole/ftlbranch chmod 644 /etc/pihole/ftlbranch elif [[ "${1}" == "core" ]] ; then - str="Fetching branches from ${piholeGitUrl}" + str="Fetching branches/tags from ${piholeGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then echo -e "${OVER} ${CROSS} $str" exit 1 fi - corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}")) + corerefs=("$(get_available_refs "${PI_HOLE_FILES_DIR}")") - if [[ "${corebranches[*]}" == *"master"* ]]; then + if [[ "${corerefs[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" - echo -e " ${INFO} ${#corebranches[@]} branches available for Pi-hole Core" + echo -e " ${INFO} ${#corerefs[@]} branches/tags available for Pi-hole Core" else - # Print STDERR output from get_available_branches - echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}" + # Print STDERR output from get_available_refs + echo -e "${OVER} ${CROSS} $str\\n\\n${corerefs[*]}" exit 1 fi echo "" - # Have the user choose the branch they want - if ! (for e in "${corebranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then - echo -e " ${INFO} Requested branch \"${2}\" is not available" - echo -e " ${INFO} Available branches for Core are:" - for e in "${corebranches[@]}"; do echo " - $e"; done + # Have the user choose the branch/tag they want + if ! (for e in "${corerefs[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then + echo -e " ${INFO} Requested branch/tag \"${2}\" is not available" + echo -e " ${INFO} Available branches/tags for Core are:" + for e in "${corerefs[@]}"; do echo " - $e"; done exit 1 fi - checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}" + checkout_pull_ref "${PI_HOLE_FILES_DIR}" "${2}" elif [[ "${1}" == "web" ]] && [[ "${INSTALL_WEB_INTERFACE}" == "true" ]] ; then - str="Fetching branches from ${webInterfaceGitUrl}" + str="Fetching branches/tags from ${webInterfaceGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${webInterfaceDir}" ; then echo -e "${OVER} ${CROSS} $str" exit 1 fi - webbranches=($(get_available_branches "${webInterfaceDir}")) + webrefs=("$(get_available_refs "${webInterfaceDir}")") - if [[ "${webbranches[*]}" == *"master"* ]]; then + if [[ "${webrefs[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" - echo -e " ${INFO} ${#webbranches[@]} branches available for Web Admin" + echo -e " ${INFO} ${#webrefs[@]} branches/tags available for Web Admin" else - # Print STDERR output from get_available_branches - echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}" + # Print STDERR output from get_available_refs + echo -e "${OVER} ${CROSS} $str\\n\\n${webrefs[*]}" exit 1 fi echo "" - # Have the user choose the branch they want - if ! (for e in "${webbranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then - echo -e " ${INFO} Requested branch \"${2}\" is not available" - echo -e " ${INFO} Available branches for Web Admin are:" - for e in "${webbranches[@]}"; do echo " - $e"; done + # Have the user choose the branch/tags they want + if ! (for e in "${webrefs[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then + echo -e " ${INFO} Requested branch/tag \"${2}\" is not available" + echo -e " ${INFO} Available branches/tags for Web Admin are:" + for e in "${webrefs[@]}"; do echo " - $e"; done exit 1 fi - checkout_pull_branch "${webInterfaceDir}" "${2}" + checkout_pull_ref "${webInterfaceDir}" "${2}" # Update local and remote versions via updatechecker /opt/pihole/updatecheck.sh elif [[ "${1}" == "ftl" ]] ; then @@ -184,7 +180,7 @@ checkout() { /opt/pihole/updatecheck.sh else echo " ${CROSS} Requested branch \"${2}\" is not available" - ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') ) + ftlbranches=("$(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}')") echo -e " ${INFO} Available branches for FTL are:" for e in "${ftlbranches[@]}"; do echo " - $e"; done exit 1 diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index c41c9232..9bd553fe 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -36,15 +36,17 @@ source "/opt/pihole/COL_TABLE" GitCheckUpdateAvail() { local directory local curBranch + local ref_is_tag directory="${1}" curdir=$PWD cd "${directory}" || return # Fetch latest changes in this repo - git fetch --quiet origin + git fetch --tags --quiet origin # Check current branch. If it is master, then check for the latest available tag instead of latest commit. - curBranch=$(git rev-parse --abbrev-ref HEAD) + # Remove any leading "heads/" as $curBranch is later used to check if local branch is remote branch or tag + curBranch=$(git rev-parse --abbrev-ref HEAD| sed "s/^heads\///g") if [[ "${curBranch}" == "master" ]]; then # get the latest local tag LOCAL=$(git describe --abbrev=0 --tags master) @@ -56,14 +58,26 @@ GitCheckUpdateAvail() { # need @{0} LOCAL="$(git rev-parse "@{0}")" - # The suffix @{upstream} to a branchname - # (short form @{u}) refers - # to the branch that the branch specified - # by branchname is set to build on top of# - # (configured with branch..remote and - # branch..merge). A missing branchname - # defaults to the current one. - REMOTE="$(git rev-parse "@{upstream}")" + # check if the local branch ef is a branch or a tag on remote repo + if git show-ref -q --verify "refs/remotes/origin/$curBranch" 2>/dev/null; then + ref_is_tag=false + elif git show-ref -q --verify "refs/tags/$curBranch" 2>/dev/null; then + ref_is_tag=true + fi + if [ "$ref_is_tag" = true ]; then + # as there is no tracking upstream branch for a checked out tag, there is need to + # check for updates + REMOTE="${LOCAL}" + else + # The suffix @{upstream} to a branchname + # (short form @{u}) refers + # to the branch that the branch specified + # by branchname is set to build on top of# + # (configured with branch..remote and + # branch..merge). A missing branchname + # defaults to the current one. + REMOTE="$(git rev-parse "@{upstream}")" + fi fi diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 24fe9e54..62b29b70 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -460,6 +460,7 @@ update_repo() { # This helps prevent the wrong value from being assigned if you were to set the variable as a GLOBAL one local directory="${1}" local curBranch + local ref_is_branch # A variable to store the message we want to display; # Again, it's useful to store these in variables in case we need to reuse or change the message; @@ -472,11 +473,26 @@ update_repo() { # Stash any local commits as they conflict with our working code git stash --all --quiet &> /dev/null || true # Okay for stash failure git clean --quiet --force -d || true # Okay for already clean directory - # Pull the latest commits - git pull --no-rebase --quiet &> /dev/null || return $? - # Check current branch. If it is master, then reset to the latest available tag. + + # Check current branch. + # Remove any leading "heads/" as $curBranch is later used to check if local branch is remote branch or tag + curBranch=$(git rev-parse --abbrev-ref HEAD| sed "s/^heads\///g") + + # check if the local branch ef is a branch or a tag on remote repo + if git show-ref -q --verify "refs/remotes/origin/$curBranch" 2>/dev/null; then + ref_is_branch=true + elif git show-ref -q --verify "refs/tags/$curBranch" 2>/dev/null; then + ref_is_branch=false + fi + + # only pull if we are on a branch not a tag + if [ "$ref_is_branch" = true ]; then + # Pull the latest commits + git pull --no-rebase --quiet &> /dev/null || return $? + fi + + # If the current branch is master, then reset to the latest available tag. # In case extra commits have been added after tagging/release (i.e in case of metadata updates/README.MD tweaks) - curBranch=$(git rev-parse --abbrev-ref HEAD) if [[ "${curBranch}" == "master" ]]; then git reset --hard "$(git describe --abbrev=0 --tags)" || return $? fi @@ -2099,28 +2115,28 @@ check_download_exists() { } fully_fetch_repo() { - # Add upstream branches to shallow clone + # Add upstream branches/tags to shallow clone local directory="${1}" cd "${directory}" || return 1 if is_repo "${directory}"; then git remote set-branches origin '*' || return 1 - git fetch --quiet || return 1 + git fetch --tags --quiet || return 1 else return 1 fi return 0 } -get_available_branches() { - # Return available branches +get_available_refs() { + # Return available branches and tags local directory directory="${1}" local output cd "${directory}" || return 1 - # Get reachable remote branches, but store STDERR as STDOUT variable - output=$( { git ls-remote --heads --quiet | cut -d'/' -f3- -; } 2>&1 ) + # Get reachable remote branches and tags, but store STDERR as STDOUT variable + output=$( { git ls-remote --heads --tags --quiet | cut -d'/' -f3- -; } 2>&1 ) # echo status for calling function to capture echo "$output" return @@ -2139,35 +2155,52 @@ fetch_checkout_pull_branch() { git stash --all --quiet &> /dev/null || true git clean --quiet --force -d || true git fetch --quiet || return 1 - checkout_pull_branch "${directory}" "${branch}" || return 1 + checkout_pull_ref "${directory}" "${branch}" || return 1 } -checkout_pull_branch() { - # Check out specified branch +checkout_pull_ref() { + # Check out specified branch/tag local directory directory="${1}" - local branch - branch="${2}" - local oldbranch + local ref + ref="${2}" + local oldref + local ref_is_tag cd "${directory}" || return 1 - oldbranch="$(git symbolic-ref HEAD)" + # Get current branch name. + oldref="$(git symbolic-ref --quiet HEAD)" - str="Switching to branch: '${branch}' from '${oldbranch}'" + str="Switching to branch/tag: '${ref}' from '${oldref}'" printf " %b %s" "${INFO}" "$str" - git checkout "${branch}" --quiet || return 1 - printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str" - # Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git) - chmod -R a+rX "${directory}" - git_pull=$(git pull --no-rebase || return 1) + # check if the ref is a branch or a tag on the remote repo + if git show-ref -q --verify "refs/remotes/origin/$ref" 2>/dev/null; then + ref_is_tag=false + elif git show-ref -q --verify "refs/tags/$ref" 2>/dev/null; then + ref_is_tag=true + fi + + if [ "$ref_is_tag" = true ]; then + # in case we want to checkout a tag we need explicitly create a new branch/reset the existing one + git checkout -B "${ref}" "refs/tags/${ref}" --quiet || return 1 + printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str" + else + # checkout a branch, this also sets tracking branch + git checkout "${ref}" --quiet || return 1 + printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str" + git_pull=$(git pull --no-rebase || return 1) + printf " %b %s\\n" "${INFO}" "${git_pull}" + fi - printf " %b %s\\n" "${INFO}" "${git_pull}" + # Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git) + chmod -R a+rX "${directory}" return 0 } + clone_or_update_repos() { # If the user wants to reconfigure, if [[ "${reconfigure}" == true ]]; then