diff --git a/build-tools/branching/branch_and_tag.sh b/build-tools/branching/branch_and_tag.sh deleted file mode 100755 index dd9e3077..00000000 --- a/build-tools/branching/branch_and_tag.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -# The purpose of this script is to create branches and tags that follow a convention -# If the desired branch already exists, it is skipped. -# If the desired tag already exists, it is skipped. - -OLD_TAG=vCGCS_DEV_0018 -NEW_TAG=vCGCS_DEV_0019 - -OLD_BRANCH=CGCS_DEV_0018 -NEW_BRANCH=CGCS_DEV_0019 - -if [ -z "$MY_REPO" ]; then - echo "MY_REPO is unset" - exit 1 -else - echo "MY_REPO is set to '$MY_REPO'" -fi - -if [ -d "$MY_REPO" ]; then - cd $MY_REPO - echo "checking out and pulling old branch" - wrgit checkout $OLD_BRANCH - if [ $? -ne 0 ]; then - echo "ERROR: wrgit checkout $OLD_BRANCH" - exit 1 - fi - - wrgit pull - if [ $? -ne 0 ]; then - echo "ERROR: wrgit pull" - exit 1 - fi -else - echo "Could not change to diectory '$MY_REPO'" - exit 1 -fi - -echo "Finding subgits" -SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"` - -# Go through all subgits and create the NEW_BRANCH if it does not already exist -# Go through all subgits and create the NEW_TAG if it does not already exist -for subgit in $SUBGITS; do - echo "" - echo "" - pushd $subgit > /dev/null - git fetch - git fetch --tags - # check if destination branch already exists - echo "$subgit" - branch_check=`git branch -a --list $NEW_BRANCH` - if [ -z "$branch_check" ]; then - echo "Creating $NEW_BRANCH" - git checkout $OLD_BRANCH - git checkout -b $NEW_BRANCH - git push origin $NEW_BRANCH:$NEW_BRANCH - else - echo "$NEW_BRANCH already exists" - fi - tag_check=`git tag -l $NEW_TAG` - if [ -z "$tag_check" ]; then - echo "Creating $NEW_TAG" - # create tag - git checkout $NEW_BRANCH - git pull origin - git tag $NEW_TAG - git push origin $NEW_TAG - else - echo "$NEW_TAG already exists" - fi - - popd > /dev/null -done - -echo "All done. branches and tags are pushed" diff --git a/build-tools/branching/create_branches_and_tags.sh b/build-tools/branching/create_branches_and_tags.sh index 01556387..a371cd13 100755 --- a/build-tools/branching/create_branches_and_tags.sh +++ b/build-tools/branching/create_branches_and_tags.sh @@ -1,54 +1,287 @@ #!/bin/bash -if [ x"$1" = x ] ; then - echo "ERROR: You must specify a name to create branches and tags" +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# Create a git branch from the current heads on a subset of git projects +# within a manifest. A tag is also created to mark the commit where +# the branch was forked from. The subset of projects affected can be +# identified by project name or remote name. +# +# Optionally a new manifest (.xml) can be created that selects +# the new branch for the affected projects. As a further option, +# projects that are not branched can me 'locked down' within the new +# manifest by setting the sha of the current head as the revision. +# +# See also: push_branches_tags.sh + +CREATE_BRANCHES_AND_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )" + +source "${CREATE_BRANCHES_AND_TAGS_SH_DIR}/../git-repo-utils.sh" + +usage () { + echo "create_branches_and_tags.sh --branch= [--tag=] [ --remotes= ] [ --projects= ] [ --manifest [ --lock-down ]]" + echo "" + echo "Create a branch and a tag in all listed projects, and all" + echo "projects hosted by all listed remotes. Lists are comma separated." + echo "" + echo "The branch name must be provided. The tag name can also be provided." + echo "If the tag is omitted, one is automativally generate by adding the" + echo "prefix 'v' to the branch name." + echo "" + echo "If a manifest is requested, it will recieve the name '.xml' and" + echo "it will specify the branch as the revision for all tagged projects." + echo "If lockdown is requested, all other projects get the current" + echo "HEAD's sha set as the revision." +} + +TEMP=$(getopt -o h --long remotes:,projects:,branch:,tag:,manifest,lock-down,help -n 'create_branches_and_tags.sh' -- "$@") +if [ $? -ne 0 ]; then + usage exit 1 fi -branch=$1 -tag="v$branch" +eval set -- "$TEMP" + +HELP=0 +MANIFEST=0 +LOCK_DOWN=0 +remotes="" +projects="" +branch="" +tag="" +manifest="" +new_manifest="" +repo_root_dir="" + +while true ; do + case "$1" in + -h|--help) HELP=1 ; shift ;; + --remotes) remotes+=$(echo "$2 " | tr ',' ' '); shift 2;; + --projects) projects+=$(echo "$2 " | tr ',' ' '); shift 2;; + --branch) branch=$2; shift 2;; + --tag) tag=$2; shift 2;; + --manifest) MANIFEST=1 ; shift ;; + --lock-down) LOCK_DOWN=1 ; shift ;; + --) shift ; break ;; + *) usage; exit 1 ;; + esac +done + +if [ $HELP -eq 1 ]; then + usage + exit 0 +fi + +if [ "$branch" == "" ] ; then + echo_stderr "ERROR: You must specify a branch" + usage + exit 1 +fi + +repo_root_dir=$(repo_root) +if [ $? -ne 0 ]; then + echo_stderr "Current directory is not managed by repo." + exit 1 +fi + +if [ $MANIFEST -eq 1 ]; then + manifest=$(repo_manifest $repo_root_dir) + if [ $? -ne 0 ]; then + echo_stderr "failed to find current manifest." + exit 1 + fi + + if [ ! -f $manifest ]; then + echo_stderr "manifest file missing '$manifest'." + exit 1 + fi + + new_manifest="$(dirname $manifest)/${branch}-$(basename $manifest)" + if [ -f $new_manifest ]; then + echo_stderr "branched manifest file already present '$new_manifest'." + exit 1 + fi +fi + +for project in $projects; do + if ! repo_is_project $project; then + echo_stderr "Invalid project: $project" + echo_stderr "Valid projects are: $(repo_project_list | tr '\n' ' ')" + exit 1 + fi +done + +for remote in $remotes; do + if ! repo_is_remote $remote; then + echo_stderr "Invalid remote: $remote" + echo_stderr "Valid remotes are: $(repo_remote_list | tr '\n' ' ')" + exit 1 + fi +done + +# Add projects from listed remotes +if [ "$remotes" != "" ]; then + projects+="$(repo_project_list $remotes | tr '\n' ' ')" +fi + +# If no projects or remotes specified, process ALL projects +if [ "$projects" == "" ] && [ "$remotes" == "" ]; then + projects="$(repo_project_list)" +fi + +if [ "$projects" == "" ]; then + echo_stderr "No projects found" + exit 1 +fi + +# Provide a default tag name if not otherwise provided +if [ "$tag" == "" ]; then + tag="v$branch" +fi echo "Finding subgits" -SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"` +SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH') # Go through all subgits and create the branch and tag if they does not already exist +echo "Applying branched and tags" +( for subgit in $SUBGITS; do - echo "" - echo "" - pushd $subgit > /dev/null + ( + cd $subgit - # check if destination branch already exists - echo "$subgit" - branch_check=`git branch -a --list $branch` - if [ -z "$branch_check" ]; then - echo "Creating branch $branch" - git checkout -b $branch + review_method=$(git_repo_review_method) + if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then + git review -s > /dev/null if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git checkout -b $branch" - popd > /dev/null + echo_stderr "ERROR: failed to setup git review in ${subgit}" + exit 1 + fi + fi + + remote=$(git_repo_remote) + if [ "${remote}" == "" ]; then + remote=$(git_remote) + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${subgit}" + exit 1 + fi + fi + + remote_branch=$(git_repo_remote_branch) + if [ "${remote_branch}" == "" ]; then + remote_branch=$(git_remote_branch) + if [ "${remote_branch}" == "" ]; then + echo_stderr "ERROR: failed to determine remote branch in ${subgit}" + exit 1 + fi + fi + + # check if destination branch already exists + branch_check=$(git branch -a --list $branch) + if [ -z "$branch_check" ]; then + echo "Creating branch $branch in $subgit" + echo " git checkout -t ${remote}/${remote_branch} -b $branch" + git checkout -t ${remote}/${remote_branch} -b $branch + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to create branch '$branch' in ${subgit}" exit 1 fi - # git push origin $branch:$branch else - echo "Branch $branch already exists" + echo "Branch $branch already exists in $subgit" git checkout $branch fi - tag_check=`git tag -l $tag` + tag_check=$(git tag -l $tag) if [ -z "$tag_check" ]; then - echo "Creating tag $tag" - git tag $tag + echo "Creating tag $tag in ${subgit}" + git tag -s -m "Branch $branch" $tag if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git tag $tag" - popd > /dev/null + echo "ERROR: failed to create tag '$tag' in ${subgit}" exit 1 fi - # git push origin $tag else - echo "Tag $tag already exists" + echo "Tag '$tag' already exists in ${subgit}" + fi + ) || exit 1 +done +) || exit 1 + +if [ $MANIFEST -eq 1 ]; then + ( + new_manifest_name=$(basename "${new_manifest}") + new_manifest_dir=$(dirname "${new_manifest}") + manifest_name=$(basename "${manifest}") + manifest_dir=$(dirname "${manifest}") + + cd "${new_manifest_dir}" || exit 1 + + review_method=$(git_review_method) + if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then + git review -s > /dev/null + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to setup git review in ${new_manifest_dir}" + exit 1 + fi fi - popd > /dev/null -done + branch_check=$(git branch -a --list $branch) + if [ ! -z "$branch_check" ]; then + echo "Branch $branch already exists in ${new_manifest_dir}" + exit 1 + fi + tag_check=$(git tag -l $tag) + if [ ! -z "$tag_check" ]; then + echo "Tag '$tag' already exists in ${new_manifest_dir}" + exit 1 + fi + + remote=$(git_remote) + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${new_manifest_dir}" + exit 1 + fi + + remote_branch=$(git_remote_branch) + if [ "${remote_branch}" == "" ]; then + echo_stderr "ERROR: failed to determine remote branch in ${new_manifest_dir}" + exit 1 + fi + + echo "Creating branch '$branch' in ${new_manifest_dir}" + git checkout -t ${remote}/${remote_branch} -b $branch + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to create branch '$branch' in ${new_manifest_dir}" + exit 1 + fi + + echo "Creating tag '$tag' in ${new_manifest_dir}" + git tag -s -m "Branch $branch" $tag + if [ $? != 0 ] ; then + echo "ERROR: failed to create tag '$tag' in ${new_manifest_dir}" + exit 1 + fi + + echo "Creating manifest ${new_manifest_name}" + manifest_set_revision "${manifest}" "${new_manifest}" "$branch" ${LOCK_DOWN} $projects || exit 1 + + echo "Move manifest ${new_manifest_name}, overwriting ${manifest_name}" + \cp -f "${manifest}" "${manifest}.save" + \mv -f "${new_manifest}" "${manifest}" + + echo "Committing ${manifest_name} in ${manifest_dir}" + git add ${manifest_name} || exit 1 + git commit -s -m "Modified manifest ${manifest_name} for branch ${branch}" + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to commit new manifest ${manifest_name} in ${manifest_dir}" + exit 1 + fi + + ) || exit 1 +fi diff --git a/build-tools/branching/create_tags.sh b/build-tools/branching/create_tags.sh index 0a16eac3..0716ae65 100755 --- a/build-tools/branching/create_tags.sh +++ b/build-tools/branching/create_tags.sh @@ -1,35 +1,238 @@ #!/bin/bash -if [ x"$1" = x ] ; then - echo "ERROR: You must specify a name to create tags" +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# Create a git tag from the current heads on a subset of git projects +# within a manifest. The subset of projects affected can be +# identified by project name or remote name. +# +# Optionally a new manifest (.xml) can be created that selects +# the new tag for the affected projects. As a further option, +# projects that are not branched can me 'locked down' within the new +# manifest by setting the sha of the current head as the revision. +# +# See also: push_tags.sh + +CREATE_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )" + +source "${CREATE_TAGS_SH_DIR}/../git-repo-utils.sh" + +usage () { + echo "create_tags.sh --tag= [ --remotes= ] [ --projects= ] [ --manifest [ --manifest-prefix ] [ --lock-down ]]" + echo " " + echo "Create a git tag in all listed projects, and all projects" + echo "hosted by all listed remotes. Lists are comma separated." + echo "" + echo "If a manifest is requested, it will recieve the name '.xml' and" + echo "it will specify the tag as the revision for all tagged projects." + echo "If lockdown is requested, all non-tagged projects get the current" + echo "HEAD's sha set as the revision." +} + +TEMP=$(getopt -o h --long remotes:,projects:,tag:,manifest,manifest-prefix:,lock-down,help -n 'create_tags.sh' -- "$@") +if [ $? -ne 0 ]; then + usage + exit 1 +fi +eval set -- "$TEMP" + +HELP=0 +MANIFEST=0 +LOCK_DOWN=0 +remotes="" +projects="" +tag="" +manifest="" +new_manifest="" +manifest_prefix="" +repo_root_dir="" + +while true ; do + case "$1" in + -h|--help) HELP=1 ; shift ;; + --remotes) remotes+=$(echo "$2 " | tr ',' ' '); shift 2;; + --projects) projects+=$(echo "$2 " | tr ',' ' '); shift 2;; + --tag) tag=$2; shift 2;; + --manifest) MANIFEST=1 ; shift ;; + --manifest-prefix) manifest_prefix=$2; shift 2;; + --lock-down) LOCK_DOWN=1 ; shift ;; + --) shift ; break ;; + *) usage; exit 1 ;; + esac +done + +if [ $HELP -eq 1 ]; then + usage + exit 0 +fi + +if [ "$tag" == "" ] ; then + echo_stderr "ERROR: You must specify a tag" + usage + exit 1 +fi + +repo_root_dir=$(repo_root) +if [ $? -ne 0 ]; then + echo_stderr "Current directory is not managed by repo." + exit 1 +fi + +if [ $MANIFEST -eq 1 ]; then + manifest=$(repo_manifest $repo_root_dir) + if [ $? -ne 0 ]; then + echo_stderr "failed to find current manifest." + exit 1 + fi + + if [ ! -f $manifest ]; then + echo_stderr "manifest file missing '$manifest'." + exit 1 + fi + + new_manifest="$(dirname $manifest)/${manifest_prefix}${tag}-$(basename $manifest)" + if [ -f $new_manifest ]; then + echo_stderr "tagged manifest file already present '$new_manifest'." + exit 1 + fi +fi + +for project in $projects; do + if ! repo_is_project $project; then + echo_stderr "Invalid project: $project" + echo_stderr "Valid projects are: $(repo_project_list | tr '\n' ' ')" + exit 1 + fi +done + +for remote in $remotes; do + if ! repo_is_remote $remote; then + echo_stderr "Invalid remote: $remote" + echo_stderr "Valid remotes are: $(repo_remote_list | tr '\n' ' ')" + exit 1 + fi +done + +# Add projects from listed remotes +if [ "$remotes" != "" ]; then + projects+="$(repo_project_list $remotes | tr '\n' ' ')" +fi + +# If no projects or remotes specified, process ALL projects +if [ "$projects" == "" ] && [ "$remotes" == "" ]; then + projects="$(repo_project_list)" +fi + +if [ "$projects" == "" ]; then + echo_stderr "No projects found" exit 1 fi -tag=$1 echo "Finding subgits" -SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"` +SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH') # Go through all subgits and create the tag if it does not already exist +echo "Applying branched and tags" +( for subgit in $SUBGITS; do - echo "" - echo "" - pushd $subgit > /dev/null + ( + cd $subgit - tag_check=`git tag -l $tag` - if [ -z "$tag_check" ]; then - echo "Creating tag $tag" - git tag $tag + review_method=$(git_repo_review_method) + if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then + git review -s > /dev/null if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git tag $tag" - popd > /dev/null + echo_stderr "ERROR: failed to setup git review in ${subgit}" exit 1 fi - # git push origin $tag - else - echo "Tag $tag already exists" fi - popd > /dev/null + tag_check=$(git tag -l $tag) + if [ -z "$tag_check" ]; then + echo "Creating tag '$tag' in ${subgit}" + git tag -s -m "Tag $tag" $tag + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to create tag '$tag' in ${subgit}" + exit 1 + fi + else + echo "Tag '$tag' already exists in ${subgit}" + fi + ) || exit 1 done +) || exit 1 +if [ $MANIFEST -eq 1 ]; then + ( + new_manifest_name=$(basename "${new_manifest}") + new_manifest_dir=$(dirname "${new_manifest}") + + cd "${new_manifest_dir}" || exit 1 + + review_method=$(git_review_method) + if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then + git review -s > /dev/null + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to setup git review in ${new_manifest_dir}" + exit 1 + fi + fi + + tag_check=$(git tag -l $tag) + if [ ! -z "$tag_check" ]; then + echo "Tag '$tag' already exists in ${new_manifest_dir}" + exit 1 + fi + + remote=$(git_remote) + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${new_manifest_dir}" + exit 1 + fi + + remote_branch=$(git_remote_branch) + if [ "${remote_branch}" == "" ]; then + echo_stderr "ERROR: failed to determine remote branch in ${new_manifest_dir}" + exit 1 + fi + + new_branch="create_manifest_for_tag_${tag}" + # check if destination branch already exists + branch_check=$(git branch -a --list $new_branch) + if [ -z "$branch_check" ]; then + echo "Creating branch ${new_branch} in ${new_manifest_dir}" + git checkout -t ${remote}/${remote_branch} -b "${new_branch}" + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to create branch '${new_branch}' in ${new_manifest_dir}" + exit 1 + fi + else + echo "Branch ${branch} already exists in $subgit" + git checkout ${new_branch} + fi + + echo "Creating manifest ${new_manifest_name}" + manifest_set_revision "${manifest}" "${new_manifest}" "refs/tags/$tag" ${LOCK_DOWN} $projects || exit 1 + + echo "Committing ${new_manifest_name} in ${new_manifest_dir}" + git add ${new_manifest_name} || exit 1 + git commit -s -m "Create new manifest ${new_manifest_name}" + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to commit new manifest ${new_manifest_name} in ${new_manifest_dir}" + exit 1 + fi + + echo "Creating tag '$tag' in ${new_manifest_dir}" + git tag -s -m "Tag $tag" $tag + if [ $? != 0 ] ; then + echo_stderr "ERROR: failed to create tag '$tag' in ${new_manifest_dir}" + exit 1 + fi + ) || exit 1 +fi diff --git a/build-tools/branching/push_branches_tags.sh b/build-tools/branching/push_branches_tags.sh index 82a7914f..1f94cc42 100755 --- a/build-tools/branching/push_branches_tags.sh +++ b/build-tools/branching/push_branches_tags.sh @@ -1,42 +1,255 @@ - #!/bin/bash -if [ x"$1" = x ] ; then - echo "ERROR: You must specify a name to create branches and tags" +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# A tool to push the branches, tags, and optional manifest created by +# create_branches_and_tags.sh to the upstream source. +# +# Arguemens should match those passed to create_branches_and_tags.sh +# with the exception of '--lockdown'. +# + +PUSH_BRANCHES_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )" + +source "${PUSH_BRANCHES_TAGS_SH_DIR}/../git-repo-utils.sh" + +usage () { + echo "push_branches_tags.sh --branch= [--tag=] [ --remotes= ] [ --projects= ] [ --manifest ]" + echo "" + echo "Push a pre-existing branch and tag into all listed projects, and all" + echo "projects hosted by all listed remotes. Lists are comma separated." + echo "" + echo "The branch name must be provided. The tag name can also be provided." + echo "If the tag is omitted, one is automativally generate by adding the" + echo "prefix 'v' to the branch name." + echo "" + echo "A manifest push can also be requested.vision." +} + +TEMP=$(getopt -o h --long remotes:,projects:,branch:,tag:,manifest,help -n 'push_branches_tags.sh' -- "$@") +if [ $? -ne 0 ]; then + usage exit 1 fi -branch=$1 -tag="v$branch" +eval set -- "$TEMP" + +HELP=0 +MANIFEST=0 +remotes="" +projects="" +branch="" +tag="" +manifest="" +repo_root_dir="" + +while true ; do + case "$1" in + -h|--help) HELP=1 ; shift ;; + --remotes) remotes+=$(echo "$2 " | tr ',' ' '); shift 2;; + --projects) projects+=$(echo "$2 " | tr ',' ' '); shift 2;; + --branch) branch=$2; shift 2;; + --tag) tag=$2; shift 2;; + --manifest) MANIFEST=1 ; shift ;; + --) shift ; break ;; + *) usage; exit 1 ;; + esac +done + +if [ $HELP -eq 1 ]; then + usage + exit 0 +fi + +if [ "$branch" == "" ] ; then + echo_stderr "ERROR: You must specify a branch" + usage + exit 1 +fi + +repo_root_dir=$(repo_root) +if [ $? -ne 0 ]; then + echo_stderr "Current directory is not managed by repo." + exit 1 +fi + +if [ $MANIFEST -eq 1 ]; then + manifest=$(repo_manifest $repo_root_dir) + if [ $? -ne 0 ]; then + echo_stderr "failed to find current manifest." + exit 1 + fi + + if [ ! -f "${manifest}" ]; then + echo_stderr "manifest file missing '${manifest}'." + exit 1 + fi + + if [ ! -f "${manifest}.save" ]; then + echo_stderr "manifest file missing '${manifest}.save'." + exit 1 + fi + + # The new manifest referes to branches that are not yet available on the remotes. + # This will break some repo commands, e.g repo forall'. + # + # To get arround this we swap in the old manifest until we get passed the + # problematic commands. + \cp -f "${manifest}" "${manifest}.new" + \cp -f "${manifest}.save" "${manifest}" +fi + +for project in $projects; do + if ! repo_is_project $project; then + echo_stderr "Invalid project: $project" + echo_stderr "Valid projects are: $(repo_project_list | tr '\n' ' ')" + exit 1 + fi +done + +for remote in $remotes; do + if ! repo_is_remote $remote; then + echo_stderr "Invalid remote: $remote" + echo_stderr "Valid remotes are: $(repo_remote_list | tr '\n' ' ')" + exit 1 + fi +done + +# Add projects from listed remotes +if [ "$remotes" != "" ]; then + projects+="$(repo_project_list $remotes | tr '\n' ' ')" +fi + +# If no projects or remotes specified, process ALL projects +if [ "$projects" == "" ] && [ "$remotes" == "" ]; then + projects="$(repo_project_list)" +fi + +if [ "$projects" == "" ]; then + echo_stderr "No projects found" + exit 1 +fi + +# Provide a default tag name if not otherwise provided +if [ "$tag" == "" ]; then + tag="v$branch" +fi + echo "Finding subgits" -SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"` +SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH') # Go through all subgits and create the branch and tag if they does not already exist +( for subgit in $SUBGITS; do - echo "" - echo "" - pushd $subgit > /dev/null + ( + cd $subgit - # check if destination branch already exists - echo "$subgit" - echo "Pushing branch $branch" - git push origin $branch:$branch - if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git push origin $branch:$branch" - popd > /dev/null + branch_check=$(git branch -a --list $branch) + if [ -z "$branch_check" ]; then + echo_stderr "ERROR: Expected branch '$branch' to exist in ${subgit}" exit 1 fi - echo "Pushing tag $tag" - git push origin $tag - if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git push origin $tag" - popd > /dev/null + tag_check=$(git tag -l $tag) + if [ "${tag_check}" == "" ]; then + echo_stderr "ERROR: Expected tag '$tag' to exist in ${subgit}" exit 1 fi - popd > /dev/null + review_method=$(git_repo_review_method) + if [ "${review_method}" == "" ]; then + echo_stderr "ERROR: Failed to determine review method in ${subgit}" + exit 1 + fi + + if [ "${review_method}" == "gerrit" ]; then + remote=$(git_repo_review_remote) + else + remote=$(git_repo_remote) + fi + + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${subgit}" + exit 1 + fi + + echo "Pushing branch $branch in ${subgit}" + if [ "${review_method}" == "gerrit" ]; then + echo "git push --tags ${remote} ${branch}" + git push --tags ${remote} ${branch} + else + echo "git push --tags --set-upstream ${remote} ${branch}" + git push --tags --set-upstream ${remote} ${branch} + fi + + if [ $? != 0 ] ; then + echo_stderr "ERROR: Failed to push branch '${branch}' to remote '${remote}' in ${subgit}" + exit 1 + fi + ) done +) || exit 1 +if [ $MANIFEST -eq 1 ]; then + # restore manifest + \cp -f "${manifest}.new" "${manifest}" +fi + +if [ $MANIFEST -eq 1 ]; then + ( + manifest_name=$(basename "${manifest}") + manifest_dir=$(dirname "${manifest}") + + cd "${manifest_dir}" || exit 1 + + if [ ! -f ${manifest_name} ]; then + echo_stderr "ERROR: Expected file '${manifest_name} to exist in ${manifest_dir}" + exit 1 + fi + + branch_check=$(git branch -a --list $branch) + if [ -z "$branch_check" ]; then + echo_stderr "ERROR: Expected branch '$branch' to exist in ${manifest_dir}" + exit 1 + fi + + tag_check=$(git tag -l $tag) + if [ "${tag_check}" == "" ]; then + echo_stderr "ERROR: Expected tag '$tag' to exist in ${manifest_dir}" + exit 1 + fi + + review_method=$(git_review_method) + if [ "${review_method}" == "" ]; then + echo_stderr "ERROR: Failed to determine review method in ${manifest_dir}" + exit 1 + fi + + + remote=$(git_review_remote) + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${manifest_dir}" + exit 1 + fi + + echo "Pushing branch $branch in ${manifest_dir}" + if [ "${review_method}" == "gerrit" ]; then + # Is a reviewless push possible as part of creating a new branch in gerrit? + git push --tags ${remote} ${branch} + else + git push --tags --set-upstream ${remote} ${branch} + fi + + if [ $? != 0 ] ; then + echo_stderr "ERROR: Failed to push tag '${tag}' to remote '${remote}' in ${manifest_dir}" + exit 1 + fi + ) || exit 1 +fi diff --git a/build-tools/branching/push_tags.sh b/build-tools/branching/push_tags.sh index 8f1bf801..ef4edd90 100755 --- a/build-tools/branching/push_tags.sh +++ b/build-tools/branching/push_tags.sh @@ -1,29 +1,238 @@ #!/bin/bash -if [ x"$1" = x ] ; then - echo "ERROR: You must specify a name to push tags" +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# A tool to push the tags, and optional manifest created by +# create_tags.sh to the upstream source. +# +# Arguemens should match those passed to create_tags.sh +# with the exception of '--lockdown'. +# + +PUSH_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )" + +source "${PUSH_TAGS_SH_DIR}/../git-repo-utils.sh" + +usage () { + echo "push_tags.sh --tag= [ --remotes= ] [ --projects= ] [ --manifest [--manifest-prefix ]]" + echo " " + echo "Push a pre-existing git tag into all listed projects, and all projects" + echo "hosted by all listed remotes. Lists are comma separated." + echo "" + echo "A manifest push can also be requested." +} + +TEMP=$(getopt -o h --long remotes:,projects:,tag:,manifest,manifest-prefix:,help -n 'push_tags.sh' -- "$@") +if [ $? -ne 0 ]; then + usage exit 1 fi -tag=$1 +eval set -- "$TEMP" +HELP=0 +MANIFEST=0 +remotes="" +projects="" +tag="" +manifest="" +manifest_prefix="" +new_manifest="" +repo_root_dir="" -echo "Finding subgits" -SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"` +while true ; do + case "$1" in + -h|--help) HELP=1 ; shift ;; + --remotes) remotes+=$(echo "$2 " | tr ',' ' '); shift 2;; + --projects) projects+=$(echo "$2 " | tr ',' ' '); shift 2;; + --tag) tag=$2; shift 2;; + --manifest) MANIFEST=1 ; shift ;; + --manifest-prefix) manifest_prefix=$2; shift 2;; + --) shift ; break ;; + *) usage; exit 1 ;; + esac +done -# Go through all subgits and create the tag if it does not already exist -for subgit in $SUBGITS; do - echo "" - echo "" - pushd $subgit > /dev/null +if [ $HELP -eq 1 ]; then + usage + exit 0 +fi - echo "Creating tag $tag" - git push origin $tag - if [ $? != 0 ] ; then - echo "ERROR: Could not exec: git push origin $tag" - popd > /dev/null +if [ "$tag" == "" ] ; then + echo_stderr "ERROR: You must specify a tags" + usage + exit 1 +fi + +repo_root_dir=$(repo_root) +if [ $? -ne 0 ]; then + echo_stderr "Current directory is not managed by repo." + exit 1 +fi + +if [ $MANIFEST -eq 1 ]; then + manifest=$(repo_manifest $repo_root_dir) + if [ $? -ne 0 ]; then + echo_stderr "failed to find current manifest." exit 1 fi - popd > /dev/null + if [ ! -f $manifest ]; then + echo_stderr "manifest file missing '$manifest'." + exit 1 + fi + + new_manifest="$(dirname $manifest)/${manifest_prefix}${tag}-$(basename $manifest)" + if [ ! -f $new_manifest ]; then + echo_stderr "Expected a tagged manifest file already present '$new_manifest'." + exit 1 + fi +fi + +for project in $projects; do + if ! repo_is_project $project; then + echo_stderr "Invalid project: $project" + echo_stderr "Valid projects are: $(repo_project_list | tr '\n' ' ')" + exit 1 + fi done +for remote in $remotes; do + if ! repo_is_remote $remote; then + echo_stderr "Invalid remote: $remote" + echo_stderr "Valid remotes are: $(repo_remote_list | tr '\n' ' ')" + exit 1 + fi +done + +# Add projects from listed remotes +if [ "$remotes" != "" ]; then + projects+="$(repo_project_list $remotes | tr '\n' ' ')" +fi + +# If no projects or remotes specified, process ALL projects +if [ "$projects" == "" ] && [ "$remotes" == "" ]; then + projects="$(repo_project_list)" +fi + +if [ "$projects" == "" ]; then + echo_stderr "No projects found" + exit 1 +fi + + +echo "Finding subgits" +SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH') + +# Go through all subgits and create the tag if it does not already exist +( +for subgit in $SUBGITS; do + ( + cd $subgit + tag_check=$(git tag -l $tag) + if [ "${tag_check}" == "" ]; then + echo_stderr "ERROR: Expected tag '$tag' to exist in ${subgit}" + exit 1 + fi + + review_method=$(git_repo_review_method) + if [ "${review_method}" == "" ]; then + echo_stderr "ERROR: Failed to determine review method in ${subgit}" + exit 1 + fi + + if [ "${review_method}" == "gerrit" ]; then + remote=$(git_repo_review_remote) + else + remote=$(git_repo_remote) + fi + + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${subgit}" + exit 1 + fi + + echo "Pushing tag $tag in ${subgit}" + if [ "${review_method}" == "gerrit" ]; then + echo "git push ${remote} ${tag}" + git push ${remote} ${tag} + else + echo "git push ${remote} ${tag}" + git push ${remote} ${tag} + fi + + if [ $? != 0 ] ; then + echo_stderr "ERROR: Failed to push tag '${tag}' to remote '${remote}' in ${subgit}" + exit 1 + fi + ) +done +) || exit 1 + +if [ $MANIFEST -eq 1 ]; then + ( + new_manifest_name=$(basename "${new_manifest}") + new_manifest_dir=$(dirname "${new_manifest}") + + cd "${new_manifest_dir}" || exit 1 + + local_branch=$(git_local_branch) + if [ "${local_branch}" == "" ]; then + echo_stderr "ERROR: failed to determine local branch in ${new_manifest_dir}" + exit 1 + fi + + remote_branch=$(git_remote_branch) + if [ "${remote_branch}" == "" ]; then + echo_stderr "ERROR: failed to determine remote branch in ${new_manifest_dir}" + exit 1 + fi + + if [ ! -f ${new_manifest_name} ]; then + echo_stderr "ERROR: Expected file '${new_manifest_name}' to exist in ${new_manifest_dir}" + exit 1 + fi + + tag_check=$(git tag -l $tag) + if [ "${tag_check}" == "" ]; then + echo_stderr "ERROR: Expected tag '$tag' to exist in ${new_manifest_dir}" + exit 1 + fi + + review_method=$(git_review_method) + if [ "${review_method}" == "" ]; then + echo_stderr "ERROR: Failed to determine review method in ${new_manifest_dir}" + exit 1 + fi + + remote=$(git_review_remote) + if [ "${remote}" == "" ]; then + echo_stderr "ERROR: Failed to determine remote in ${new_manifest_dir}" + exit 1 + fi + + echo "Pushing tag $tag in ${new_manifest_dir}" + if [ "${review_method}" == "gerrit" ]; then + git review + if [ $? != 0 ] ; then + echo_stderr "ERROR: Failed to create git review from ${new_manifest_dir}" + exit 1 + fi + echo "When review is merged: please run ..." + echo " cd ${new_manifest_dir}" + echo " git push ${remote} ${tag}" + else + git push ${remote} ${local_branch}:${remote_branch} + git push ${remote} ${tag}:${tag} + fi + + if [ $? != 0 ] ; then + echo_stderr "ERROR: Failed to push tag '${tag}' to branch ${remote_branch} on remote '${remote}' from ${new_manifest_dir}" + exit 1 + fi + ) || exit 1 +fi diff --git a/build-tools/git-repo-utils.sh b/build-tools/git-repo-utils.sh new file mode 100644 index 00000000..fc4acf85 --- /dev/null +++ b/build-tools/git-repo-utils.sh @@ -0,0 +1,229 @@ +#!/bin/bash + +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# A collection of utilities that stradle the divide between +# between git and repo. +# +# These utilites are often the most reliable to use. They will +# try to get the answer from repo, and will fall back to git +# of repo isn't providing a satisfactory answer. A prime example +# is the repo's manifest, which isn't fully managed by repo, +# but isn't a fully independent git either. +# + + +GIT_REPO_UTILS_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )" + +source ${GIT_REPO_UTILS_DIR}/repo-utils.sh +source ${GIT_REPO_UTILS_DIR}/git-utils.sh + + +# +# git_repo_rel_dir []: +# Return the relative directory of a git within a repo. +# +git_repo_rel_dir () { + local DIR="${1:-${PWD}}" + + local GIT_DIR="" + local REPO_DIR="" + local GIT_RELATIVE_DIR="" + + GIT_DIR=$(git_root ${DIR}) + REPO_DIR=$(readlink -f $(repo_root ${DIR})) + GIT_RELATIVE_DIR=${GIT_DIR#${REPO_DIR}/} + echo ${GIT_RELATIVE_DIR} +} + +# +# git_repo_project []: +# Return the repo 'project' of a git. +# + +git_repo_project() { + local DIR="${1:-${PWD}}" + + ( + cd ${DIR} + + GIT_RELATIVE_DIR=$(git_repo_rel_dir) + repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_PROJECT; fi" + ) +} + +# +# git_repo_remote []: +# Return the repo 'remote' of a git. +# + +git_repo_remote() { + local DIR="${1:-${PWD}}" + + ( + cd ${DIR} + + GIT_RELATIVE_DIR=$(git_repo_rel_dir) + repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_REMOTE; fi" + ) +} + + +# +# git_repo_remote_branch []: +# Return the repo 'remote branch' of a git. +# + +git_repo_remote_branch() { + local DIR="${1:-${PWD}}" + + ( + cd ${DIR} + + GIT_RELATIVE_DIR=$(git_repo_rel_dir) + REF=$(repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_RREV; fi") + if git_is_branch ${REF} ; then + echo ${REF} + else + return 1 + fi + ) +} + +# +# git_repo_remote_ref []: +# Return the repo 'remote branch' of a git. +# + +git_repo_remote_ref() { + local DIR="${1:-${PWD}}" + + ( + cd ${DIR} + + GIT_RELATIVE_DIR=$(git_repo_rel_dir) + repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_RREV; fi" + ) +} + +git_repo_remote_url () { + local remote="" + remote=$(git_repo_remote) || return 1 + git config remote.$remote.url +} + +url_to_host () { + local URL="${1}" + + # Strip protocol, path, user/pwd, port + echo "${URL}" | sed -e 's#^[^:]*://##' -e 's#/.*$##' -e 's#^[^@]*@##' -e 's#:.*$##' +} + +host_to_domain () { + local host="${1}" + local elements=0 + + elements=$(echo "${host}" | sed 's#[^.]##g' | wc --chars) + if [ $elements -gt 2 ]; then + # strip lead element + echo "${host}" | sed 's#^[^.]*.##' + else + echo "${host}" + fi +} + +git_repo_review_method () { + local DIR="${1:-${PWD}}" + local GIT_DIR="" + local remote_url="" + local review_host="" + local remote_host="" + + GIT_DIR=$(git_root ${DIR}) || return 1 + + if [ ! -f ${GIT_DIR}/.gitreview ]; then + # No .gitreview file + echo 'default' + return 0 + fi + + if ! grep -q '\[gerrit\]' ${GIT_DIR}/.gitreview; then + # .gitreview file has no gerrit entry + echo 'default' + return 0 + fi + + review_host="$(grep host= ${GIT_DIR}/.gitreview | sed 's#^host=##' | head -n 1)" + remote_url="$(git_repo_remote_url)" || return 1 + remote_host="$(url_to_host "${remote_url}")" + if [ "${review_host}" == "{remote_host}" ]; then + # Will review against same host as we pulled from. All is well + echo 'gerrit' + return 0 + else + review_domain="$(host_to_domain "${review_host}")" + remote_domain="$(host_to_domain "${remote_host}")" + if [ "${review_domain}" == "${remote_domain}" ]; then + # Will review and remote hosts share a commom domain. Close enough + + echo 'gerrit' + return 0 + else + # Domains don't match. Not close enough to say gerrit is safe. + # Did someone forget to update .gitreview? + # Are we not pulling from the authoritative source? + + echo 'default' + return 0 + fi + fi + + # Shouldn't get here + return 1 +} + +git_repo_review_remote () { + local method="" + method=$(git_repo_review_method) + if [ "${method}" == "gerrit" ]; then + git config remote.gerrit.url > /dev/null + if [ $? -ne 0 ]; then + # Perhaps we need to run git review -s' and try again + + # echo a blank line into git in case it prompts for a username + echo | git review -s > /dev/null || return 1 + git config remote.gerrit.url > /dev/null || return 1 + fi + echo "gerrit" + else + git_repo_remote + fi +} + +git_repo_review_url () { + local DIR="${1:-${PWD}}" + local GIT_DIR="" + + GIT_DIR=$(git_root ${DIR}) + + local method="" + method=$(git_repo_review_method) + if [ "${method}" == "gerrit" ]; then + git config remote.gerrit.url + if [ $? -ne 0 ]; then + # Perhaps we need to run git review -s' and try again + + # echo a blank line into git in case it prompts for a username + echo | git review -s > /dev/null || return 1 + git config remote.gerrit.url || return 1 + fi + else + return 1 + fi +} + diff --git a/build-tools/git-utils.sh b/build-tools/git-utils.sh index 47e156b2..8e27001e 100755 --- a/build-tools/git-utils.sh +++ b/build-tools/git-utils.sh @@ -1,3 +1,5 @@ +#!/bin/bash + # # Copyright (c) 2018 Wind River Systems, Inc. # @@ -9,6 +11,11 @@ # by repo manifests. # +echo_stderr () +{ + echo "$@" >&2 +} + git_ctx_root_dir () { dirname "${MY_REPO}" } @@ -80,6 +87,243 @@ git_list_containing_tag () { } +# +# git_root []: +# Return the root directory of a git +# Note: symlinks are fully expanded. +# + +git_root () { + local DIR="${1:-${PWD}}" + + if [ ! -d "${DIR}" ]; then + echo_stderr "No such directory: ${DIR}" + return 1 + fi + + ( + cd "${DIR}" + ROOT_DIR="$(git rev-parse --show-toplevel)" || exit 1 + readlink -f "${ROOT_DIR}" + ) +} + +# +# git_list_tags []: +# Return a list of all git tags. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_list_tags () { + local DIR="${1:-${PWD}}" + + ( + cd "$DIR" + git tag + ) +} + + +# +# git_list_branches []: +# Return a list of all git branches. +# Non-local branches will be prefixed by 'remote/' +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_list_branches () { + local DIR="${1:-${PWD}}" + + ( + cd "$DIR" + git branch --list --all | sed 's#^..##' + ) +} + + +# +# git_list_remote_branches []: +# Return a list of all git branches defined for . +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_list_remote_branches () { + local REMOTE="${1}" + local DIR="${2:-${PWD}}" + + ( + cd "$DIR" + git branch --list --all "${REMOTE}/*" | sed "s#^.*/${REMOTE}/##" + ) +} + + +# +# git_is_tag []: +# Test if a is defined within a git. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_tag () { + local TAG="${1}" + local DIR="${2:-${PWD}}" + + # remove a trailing ^0 if present + TAG=${TAG%^0} + + if [ "$TAG" == "" ]; then + return 1; + fi + + ( + cd "$DIR" + git show-ref ${TAG} | cut -d ' ' -f 2 | grep -q '^refs/tags/' + ) +} + + +# +# git_is_local_branch []: +# Test if a is defined locally within a git. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_local_branch () { + local BRANCH="${1}" + local DIR="${2:-${PWD}}" + + if [ "$BRANCH" == "" ]; then + return 1; + fi + + ( + cd "$DIR" + git show-ref ${BRANCH} | cut -d ' ' -f 2 | grep -q '^refs/heads/' + ) +} + + +# +# git_is_remote_branch []: +# Test if a is defined in any of the remotes of the git. +# The branche does NOT need to be prefixed by the remore name. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_remote_branch () { + local BRANCH="${1}" + local DIR="${2:-${PWD}}" + + if [ "$BRANCH" == "" ]; then + return 1; + fi + + ( + cd "$DIR" + git show-ref ${BRANCH} | cut -d ' ' -f 2 | grep -q '^refs/remotes/' + ) +} + + +# +# git_is_branch []: +# Test if a is defined in the git. +# The branch can be local or remote. +# Remote branches do NOT need to be prefixed by the remore name. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_branch () { + local BRANCH="${1}" + local DIR="${2:-${PWD}}" + + if [ "$BRANCH" == "" ]; then + return 1; + fi + + git_is_local_branch ${BRANCH} "${DIR}" || git_is_remote_branch ${BRANCH} "${DIR}" +} + + +# +# git_is_ref []: +# Test if a is a valid name for a commit. +# The reference can be a sha, tag, or branch. +# Remote branches must be prefixed by the remore name, +# as in / . +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_ref () { + local REF="${1}" + local DIR="${2:-${PWD}}" + + if [ "$REF" == "" ]; then + return 1; + fi + + # test "$(git cat-file -t ${REF})" == "commit" + local TYPE="" + TYPE="$(git cat-file -t ${REF} 2> /dev/null)" && test "${TYPE}" == "commit" +} + + +# +# git_is_sha []: +# Test if a is defined in the git. The sha can be abreviated. +# Either specify a directory in the git, +# or use current directory if unspecified. +# + +git_is_sha () { + local SHA="${1}" + local DIR="${2:-${PWD}}" + + if [ "$SHA" == "" ]; then + return 1; + fi + + git_is_ref ${SHA} "${DIR}" && ! ( git_is_branch ${SHA} "${DIR}" || git_is_tag ${SHA} "${DIR}") +} + + +# +# git_ref_type []: +# Determine the type of the git reference . +# The result, via stdout, will be one of ("sha", "tag", "branch" or "invalid") +# Remote branches do NOT need to be prefixed by the remore name. +# Either specify a directory in the git, +# or use current directory if unspecified. + +git_ref_type () { + local REF="${1}" + local DIR="${2:-${PWD}}" + + if git_is_branch ${REF} ${DIR}; then + echo 'branch' + return 0 + fi + if git_is_tag ${REF} ${DIR}; then + echo 'tag' + return 0 + fi + if git_is_sha ${REF} ${DIR}; then + echo 'sha' + return 0 + fi + echo 'invalid' + return 1 +} + +# # # git_context: # Returns a bash script that can be used to recreate the current git context, @@ -146,3 +390,92 @@ git_test_context () { return 1 } + +git_local_branch () { + local result="" + result=$(git name-rev --name-only HEAD) + if [ "$result" == "" ] || [ "$result" == "undefined" ]; then + return 1 + fi + + # handle the case where a tag is returned by looking at the parent. + # This weird case when a local commit is tagged and we were in + # detached head state, or on 'default' branch. + while git_is_tag $result; do + result=$(git name-rev --name-only $result^1 ) + if [ "$result" == "" ] || [ "$result" == "undefined" ]; then + return 1 + fi + done + + echo $result +} + +git_list_remotes () { + git remote | grep -v gerrit +} + +git_remote () { + local DIR="${1:-${PWD}}" + + ( + cd ${DIR} + local_branch=$(git_local_branch) || return 1 + + # Return remote of current local branch, else default remote. + git config branch.${local_branch}.remote || git_list_remotes + ) +} + +git_remote_url () { + local remote="" + remote=$(git_remote) || return 1 + git config remote.$remote.url +} + +git_remote_branch () { + local local_branch="" + local_branch=$(git_local_branch) || return 1 + git config branch.${local_branch}.merge | sed 's#^refs/heads/##' +} + +git_review_method () { + local url="" + url=$(git_remote_url) || exit 1 + if [[ "${url}" =~ "/git.starlingx.io/" || "${url}" =~ "/opendev.org/" ]]; then + echo 'gerrit' + else + echo 'default' + fi +} + +git_review_url () { + local method="" + method=$(git_review_method) + if [ "${method}" == "gerrit" ]; then + git config remote.gerrit.url + if [ $? -ne 0 ]; then + # Perhaps we need to run git review -s' and try again + git review -s > /dev/null || return 1 + git config remote.gerrit.url + fi + else + git_remote_url + fi +} + +git_review_remote () { + local method="" + method=$(git_review_method) + if [ "${method}" == "gerrit" ]; then + git config remote.gerrit.url > /dev/null + if [ $? -ne 0 ]; then + # Perhaps we need to run git review -s' and try again + git review -s > /dev/null || return 1 + git config remote.gerrit.url > /dev/null || return 1 + fi + echo "gerrit" + else + git_remote + fi +} diff --git a/build-tools/repo-utils.sh b/build-tools/repo-utils.sh new file mode 100644 index 00000000..b8db2ee1 --- /dev/null +++ b/build-tools/repo-utils.sh @@ -0,0 +1,237 @@ +#!/bin/bash + +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# A collection of utilities relating to 'repo' +# + + +# +# Echo to stderr +# echo_stderr [any text you want] +# + +echo_stderr () +{ + echo "$@" >&2 +} + +# +# Get the root dir of a repo managed repository +# repo_root [] +# + +repo_root () { + local query_dir="${1:-${PWD}}" + local work_dir + + if [ ! -d "${query_dir}" ]; then + echo_stderr "not a valid directory: ${query_dir}" + return 1 + fi + + if [ "${query_dir:0:1}" != "/" ]; then + query_dir=$(readlink -f ${query_dir}) + if [ $? -ne 0 ]; then + return 1 + fi + fi + + work_dir="${query_dir}" + while true; do + if [ -d "$work_dir/.repo/manifests" ]; then + echo $work_dir + return 0 + fi + + if [ "${work_dir}" == "/" ]; then + break + fi + + work_dir="$(dirname "${work_dir}")" + done + + echo_stderr "directory is not controlled by repo: ${query_dir}" + return 1 +} + +# +# Get the active manifest file of a repo managed repository +# repo_manifest [] +# + +repo_manifest () { + local query_dir="${1:-${PWD}}" + local root_dir="" + local repo_manifest="" + + root_dir="$(repo_root "${query_dir}")" + if [ $? -ne 0 ]; then + return 1 + fi + + repo_manifest="${root_dir}/.repo/manifest.xml" + + # Depending on repo version, ${repo_manifest} is either a symlink to + # the real manifest, or a wrapper manifest that includes the real manifest + if [ -L "${repo_manifest}" ]; then + readlink -f "${repo_manifest}" + else + grep " +# +# old_manifest = Path to original manifest. +# new_manifest = Path to modified manifest. It will not overwrite an +# existing file. +# revision = A branch, tag ,or sha. Branch and SHA can be used +# directly, but repo requires that a tag be in the form +# "refs/tags/". +# lock_down = 0 or 1. If 1, set a revision on all other non-listed +# projects to equal the SHA of the current git head. +# project-list = A space seperated list of projects. Listed projects +# will have their revision set to the provided revision +# value. +# +manifest_set_revision () { + local old_manifest="${1}" + local new_manifest="${2}" + local revision="${3}" + local lock_down="${4}" + shift 4 + local projects="${@}" + + local repo_root_dir="" + local line="" + local FOUND=0 + local path="" + local project="" + local rev="" + + repo_root_dir=$(repo_root) + if [ $? -ne 0 ]; then + echo_stderr "Current directory is not managed by repo." + return 1 + fi + + if [ ! -f "${old_manifest}" ]; then + echo_stderr "Old manifest file is missing '${old_manifest}'." + return 1 + fi + + if [ -f "${new_manifest}" ]; then + echo_stderr "New manifest file already present '${new_manifest}'." + return 1 + fi + + mkdir -p "$(dirname "${new_manifest}")" + if [ $? -ne 0 ]; then + echo_stderr "Failed to create directory '$(dirname "${new_manifest}")'" + return 1 + fi + + while IFS= read -r line; do + echo "${line}" | grep -q '