diff options
Diffstat (limited to 'Utilities/GitSetup')
-rw-r--r-- | Utilities/GitSetup/.gitattributes | 6 | ||||
-rw-r--r-- | Utilities/GitSetup/README | 7 | ||||
-rw-r--r-- | Utilities/GitSetup/config.sample | 10 | ||||
-rwxr-xr-x | Utilities/GitSetup/git-gerrit-push | 74 | ||||
-rwxr-xr-x | Utilities/GitSetup/git-gitlab-push | 177 | ||||
-rwxr-xr-x | Utilities/GitSetup/setup-gerrit | 15 | ||||
-rwxr-xr-x | Utilities/GitSetup/setup-gitlab | 140 | ||||
-rwxr-xr-x | Utilities/GitSetup/setup-hooks | 1 | ||||
-rwxr-xr-x | Utilities/GitSetup/setup-stage | 9 | ||||
-rwxr-xr-x | Utilities/GitSetup/setup-upstream | 104 |
10 files changed, 532 insertions, 11 deletions
diff --git a/Utilities/GitSetup/.gitattributes b/Utilities/GitSetup/.gitattributes index facbbb2..f7531d4 100644 --- a/Utilities/GitSetup/.gitattributes +++ b/Utilities/GitSetup/.gitattributes @@ -1,7 +1,7 @@ .git* export-ignore +.gitattributes -export-ignore -# Exclude from source archives files specific to Git work tree. -* export-ignore - +config* eol=lf whitespace=indent-with-non-tab +git-* eol=lf whitespace=indent-with-non-tab tips eol=lf whitespace=indent-with-non-tab setup-* eol=lf whitespace=indent-with-non-tab diff --git a/Utilities/GitSetup/README b/Utilities/GitSetup/README index cf468fb..2f9f1ec 100644 --- a/Utilities/GitSetup/README +++ b/Utilities/GitSetup/README @@ -37,6 +37,13 @@ Commit the merge with an informative message: the general GitSetup repository "setup" branch. ------------------------------------------------------------------------ +Optionally add to the project ".gitattributes" file the line + + /Utilities/GitSetup export-ignore + +to exclude the GitSetup directory from inclusion by "git archive" +since it does not make sense in source tarballs. + Configuration ------------- diff --git a/Utilities/GitSetup/config.sample b/Utilities/GitSetup/config.sample index bba2382..eeb468b 100644 --- a/Utilities/GitSetup/config.sample +++ b/Utilities/GitSetup/config.sample @@ -20,3 +20,13 @@ site = http://review.source.kitware.com # pushurl placeholder "$username" is literal pushurl = $username@review.source.kitware.com:Project + +[upstream] + url = git://public.kitware.com/Project.git + +[gitlab] + host = gitlab.kitware.com + group-path = group + group-name = Group + project-path = project + project-name = Project diff --git a/Utilities/GitSetup/git-gerrit-push b/Utilities/GitSetup/git-gerrit-push new file mode 100755 index 0000000..b46f753 --- /dev/null +++ b/Utilities/GitSetup/git-gerrit-push @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +#============================================================================= +# Copyright 2010-2015 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +USAGE="[<remote>] [--no-topic] [--dry-run] [--]" +OPTIONS_SPEC= +SUBDIRECTORY_OK=Yes +. "$(git --exec-path)/git-sh-setup" + +#----------------------------------------------------------------------------- + +remote='' +refspecs='' +no_topic='' +dry_run='' + +# Parse the command line options. +while test $# != 0; do + case "$1" in + --no-topic) no_topic=1 ;; + --dry-run) dry_run=--dry-run ;; + --) shift; break ;; + -*) usage ;; + *) test -z "$remote" || usage ; remote="$1" ;; + esac + shift +done +test $# = 0 || usage + +# Default remote. +test -n "$remote" || remote="gerrit" + +if test -z "$no_topic"; then + # Identify and validate the topic branch name. + head="$(git symbolic-ref HEAD)" && topic="${head#refs/heads/}" || topic='' + if test -z "$topic" -o "$topic" = "master"; then + die 'Please name your topic: + git checkout -b descriptive-name' + fi + # The topic branch will be pushed by name. + refspecs="HEAD:refs/for/master/$topic $refspecs" +fi + +# Fetch the current upstream master branch head. +# This helps computation of a minimal pack to push. +echo "Fetching $remote master" +fetch_out=$(git fetch "$remote" master 2>&1) || die "$fetch_out" + +# Exit early if we have nothing to push. +if test -z "$refspecs"; then + echo 'Nothing to push!' + exit 0 +fi + +# Push. Save output and exit code. +echo "Pushing to $remote" +push_stdout=$(git push --porcelain $dry_run "$remote" $refspecs); push_exit=$? +echo "$push_stdout" + +# Reproduce the push exit code. +exit $push_exit diff --git a/Utilities/GitSetup/git-gitlab-push b/Utilities/GitSetup/git-gitlab-push new file mode 100755 index 0000000..768f853 --- /dev/null +++ b/Utilities/GitSetup/git-gitlab-push @@ -0,0 +1,177 @@ +#!/usr/bin/env bash +#============================================================================= +# Copyright 2010-2015 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +USAGE='[<remote>] [<options>...] [--] + +OPTIONS + +--dry-run + Show what would be pushed without actually updating the destination + +-f,--force + Force-push the topic HEAD to rewrite the destination branch + +--no-default + Do not push the default branch (e.g. master) + +--no-topic + Do not push the topic HEAD. +' +OPTIONS_SPEC= +SUBDIRECTORY_OK=Yes +. "$(git --exec-path)/git-sh-setup" + +egrep-q() { + egrep "$@" >/dev/null 2>/dev/null +} + +# Load the project configuration. +gitlab_upstream='' && +gitlab_configured='' && +config="${BASH_SOURCE%/*}/config" && +protocol=$(git config -f "$config" --get gitlab.protocol || + echo "https") && +host=$(git config -f "$config" --get gitlab.host) && +site=$(git config -f "$config" --get gitlab.site || + echo "$protocol://$host") && +group_path=$(git config -f "$config" --get gitlab.group-path) && +project_path=$(git config -f "$config" --get gitlab.project-path) && +gitlab_upstream="$site/$group_path/$project_path.git" && +gitlab_pushurl=$(git config --get remote.gitlab.pushurl || + git config --get remote.gitlab.url) && +gitlab_configured=1 + +#----------------------------------------------------------------------------- + +remote='' +refspecs='' +force='' +lease=false +lease_flag='' +no_topic='' +no_default='' +dry_run='' + +# Parse the command line options. +while test $# != 0; do + case "$1" in + -f|--force) force='+'; lease=true ;; + --no-topic) no_topic=1 ;; + --dry-run) dry_run=--dry-run ;; + --no-default) no_default=1 ;; + --) shift; break ;; + -*) usage ;; + *) test -z "$remote" || usage ; remote="$1" ;; + esac + shift +done +test $# = 0 || usage + +# Default remote. +test -n "$remote" || remote="gitlab" + +if test -z "$no_topic"; then + # Identify and validate the topic branch name. + head="$(git symbolic-ref HEAD)" && topic="${head#refs/heads/}" || topic='' + if test -z "$topic" -o "$topic" = "master"; then + die 'Please name your topic: + git checkout -b descriptive-name' + fi + + if $lease; then + have_ref=false + remoteref="refs/remotes/$remote/$topic" + if git rev-parse --verify -q "$remoteref"; then + have_ref=true + else + die "It seems that a local ref for the branch is +missing; forcing a push is dangerous and may overwrite +previous work. Fetch from the $remote remote first or +push without '-f' or '--force'." + fi + + have_lease_flag=false + if git push -h | egrep-q -e '--force-with-lease'; then + have_lease_flag=true + fi + + if $have_lease_flag && $have_ref; then + # Set the lease flag. + lease_flag="--force-with-lease=$topic:$remoteref" + # Clear the force string. + force='' + fi + fi + + # The topic branch will be pushed by name. + refspecs="${force}HEAD:refs/heads/$topic $refspecs" +fi + +# Fetch the current remote master branch head. +# This helps computation of a minimal pack to push. +echo "Fetching $remote master" +fetch_out=$(git fetch "$remote" master 2>&1) || die "$fetch_out" +gitlab_head=$(git rev-parse FETCH_HEAD) || exit + +# Fetch the current upstream master branch head. +if origin_fetchurl=$(git config --get remote.origin.url) && + test "$origin_fetchurl" = "$gitlab_upstream"; then + upstream_remote='origin' +else + upstream_remote="$gitlab_upstream" +fi +echo "Fetching $upstream_remote master" +fetch_out=$(git fetch "$upstream_remote" master 2>&1) || die "$fetch_out" +upstream_head=$(git rev-parse FETCH_HEAD) || exit + +# Add a refspec to keep the remote master up to date if possible. +if test -z "$no_default" && + base=$(git merge-base "$gitlab_head" "$upstream_head") && + test "$base" = "$gitlab_head"; then + refspecs="$upstream_head:refs/heads/master $refspecs" +fi + +# Exit early if we have nothing to push. +if test -z "$refspecs"; then + echo 'Nothing to push!' + exit 0 +fi + +# Push. Save output and exit code. +echo "Pushing to $remote" +push_config='-c advice.pushUpdateRejected=false' +push_stdout=$(git $push_config push $lease_flag --porcelain $dry_run "$remote" $refspecs); push_exit=$? +echo "$push_stdout" + +if test "$push_exit" -ne 0 && test -z "$force"; then + # Advise the user to fetch if needed. + if echo "$push_stdout" | egrep-q 'stale info'; then + echo " +You have pushed to your branch from another machine; you may be overwriting +commits unintentionally. Fetch from the $remote remote and check that you are +not pushing an outdated branch." + fi + + # Advise the user to force-push if needed. + if echo "$push_stdout" | egrep-q 'non-fast-forward'; then + echo ' +Add "-f" or "--force" to push a rewritten topic.' + fi +fi + +# Reproduce the push exit code. +exit $push_exit diff --git a/Utilities/GitSetup/setup-gerrit b/Utilities/GitSetup/setup-gerrit index 9e8fa62..6d46e3c 100755 --- a/Utilities/GitSetup/setup-gerrit +++ b/Utilities/GitSetup/setup-gerrit @@ -28,6 +28,7 @@ # gerrit.pushurl = Review site push URL with "$username" placeholder # gerrit.remote = Gerrit remote name, if not "gerrit" # gerrit.url = Gerrit project URL, if not "$site/p/$project" +# optionally with "$username" placeholder die() { echo 1>&2 "$@" ; exit 1 @@ -39,11 +40,12 @@ cd "${BASH_SOURCE%/*}" && # Load the project configuration. site=$(git config -f config --get gerrit.site) && project=$(git config -f config --get gerrit.project) && -pushurl_=$(git config -f config --get gerrit.pushurl) && remote=$(git config -f config --get gerrit.remote || echo "gerrit") && -fetchurl=$(git config -f config --get gerrit.url || - echo "$site/p/$project") || +fetchurl_=$(git config -f config --get gerrit.url || + echo "$site/p/$project") && +pushurl_=$(git config -f config --get gerrit.pushurl || + git config -f config --get gerrit.url) || die 'This project is not configured to use Gerrit.' # Get current gerrit push URL. @@ -67,7 +69,7 @@ else '"$project"' changes must be pushed to our Gerrit Code Review site: - '"$fetchurl"' + '"$site/p/$project"' Register a Gerrit account and select a username (used below). You will need an OpenID: @@ -96,13 +98,16 @@ Add your SSH public keys at if test -z "$gu"; then gu="$USER" fi && + fetchurl="${fetchurl_/\$username/$gu}" && if test -z "$pushurl"; then git remote add "$remote" "$fetchurl" else git config remote."$remote".url "$fetchurl" fi && pushurl="${pushurl_/\$username/$gu}" && - git config remote."$remote".pushurl "$pushurl" && + if test "$pushurl" != "$fetchurl"; then + git config remote."$remote".pushurl "$pushurl" + fi && echo 'Remote "'"$remote"'" is now configured to push to '"$pushurl"' diff --git a/Utilities/GitSetup/setup-gitlab b/Utilities/GitSetup/setup-gitlab new file mode 100755 index 0000000..9c7574d --- /dev/null +++ b/Utilities/GitSetup/setup-gitlab @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +#============================================================================= +# Copyright 2010-2015 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +# Run this script to set up the local Git repository to push to +# a personal fork for this project in GitLab. + +# Project configuration instructions: +# +# - Run a GitLab server +# +# - Populate adjacent "config" file with: +# gitlab.protocol = Top GitLab protocol, if not 'https' +# gitlab.host = Top GitLab fully qualified host name +# gitlab.site = Top GitLab URL, if not "<protocol>://<host>" +# gitlab.group-name = Name of group containing project in GitLab +# gitlab.group-path = Path of group containing project in GitLab +# gitlab.project-name = Name of project within GitLab group +# gitlab.project-path = Path of project within GitLab group +# gitlab.url = GitLab push URL with "$username" placeholder, +# if not "<site>/$username/<project-path>.git" +# gitlab.pushurl = GitLab push URL with "$username" placeholder, +# if not "git@<host>:$username/<project-path>.git" +# gitlab.remote = GitLab remote name, if not "gitlab" + +die() { + echo 1>&2 "$@" ; exit 1 +} + +# Make sure we are inside the repository. +cd "${BASH_SOURCE%/*}" && + +# Load the project configuration. +protocol=$(git config -f config --get gitlab.protocol || + echo "https") && +host=$(git config -f config --get gitlab.host) && +site=$(git config -f config --get gitlab.site || + echo "$protocol://$host") && +group_path=$(git config -f config --get gitlab.group-path) && +group_name=$(git config -f config --get gitlab.group-name) && +project_name=$(git config -f config --get gitlab.project-name) && +project_path=$(git config -f config --get gitlab.project-path) && +pushurl_=$(git config -f config --get gitlab.pushurl || + echo "git@$host:\$username/$project_path.git") && +remote=$(git config -f config --get gitlab.remote || + echo "gitlab") && +fetchurl_=$(git config -f config --get gitlab.url || + echo "$site/\$username/$project_path.git") || +die 'This project is not configured to use GitLab.' + +# Get current gitlab push URL. +pushurl=$(git config --get remote."$remote".pushurl || + git config --get remote."$remote".url || echo '') && + +# Tell user about current configuration. +if test -n "$pushurl"; then + echo 'Remote "'"$remote"'" is currently configured to push to + + '"$pushurl"' +' && + read -ep 'Reconfigure GitLab? [y/N]: ' ans && + if [ "$ans" == "y" ] || [ "$ans" == "Y" ]; then + setup=1 + else + setup='' + fi +else + echo 'Remote "'"$remote"'" is not yet configured. +' && + read -ep 'Configure GitLab to contribute to '"$project_name"'? [Y/n]: ' ans && + if [ "$ans" == "n" ] || [ "$ans" == "N" ]; then + exit 0 + else + setup=1 + fi +fi && + +setup_instructions='Add your SSH public keys at + + '"$site"'/profile/keys + +Then visit the main repository at: + + '"$site/$group_path/$project_path"' + +and use the Fork button in the upper right. +' + +# Perform setup if necessary. +if test -n "$setup"; then + echo 'Sign-in to GitLab to get/set your username at + + '"$site/profile/account"' + +'"$setup_instructions" && + read -ep "GitLab username? [$USER]: " gu && + if test -z "$gu"; then + gu="$USER" + fi && + fetchurl="${fetchurl_/\$username/$gu}" && + if test -z "$pushurl"; then + git remote add "$remote" "$fetchurl" + else + git config remote."$remote".url "$fetchurl" + fi && + pushurl="${pushurl_/\$username/$gu}" && + git config remote."$remote".pushurl "$pushurl" && + echo 'Remote "'"$remote"'" is now configured to push to + + '"$pushurl"' +' +fi && + +# Optionally test GitLab access. +if test -n "$pushurl"; then + read -ep 'Test access to GitLab (SSH)? [y/N]: ' ans && + if [ "$ans" == "y" ] || [ "$ans" == "Y" ]; then + echo -n 'Testing GitLab access by SSH...' + if git ls-remote --heads "$pushurl" >/dev/null; then + echo 'passed.' + else + echo 'failed.' && + die 'Could not access your GitLab fork of this project. +'"$setup_instructions" + fi + fi +fi diff --git a/Utilities/GitSetup/setup-hooks b/Utilities/GitSetup/setup-hooks index c07985a..ca07712 100755 --- a/Utilities/GitSetup/setup-hooks +++ b/Utilities/GitSetup/setup-hooks @@ -55,6 +55,7 @@ fi && # Populate ".git/hooks". echo 'Setting up git hooks...' && git_dir=$(git rev-parse --git-dir) && +mkdir -p "$git_dir/hooks" && cd "$git_dir/hooks" && if ! test -e .git; then git init -q || die 'Could not run git init for hooks.' diff --git a/Utilities/GitSetup/setup-stage b/Utilities/GitSetup/setup-stage index 323e47a..ce6ec45 100755 --- a/Utilities/GitSetup/setup-stage +++ b/Utilities/GitSetup/setup-stage @@ -37,8 +37,8 @@ die() { cd "${BASH_SOURCE%/*}" && # Load the project configuration. -fetchurl=$(git config -f config --get stage.url) && -pushurl_=$(git config -f config --get stage.pushurl || echo '') && +fetchurl_=$(git config -f config --get stage.url) && +pushurl_=$(git config -f config --get stage.pushurl || echo "$fetchurl_") && remote=$(git config -f config --get stage.remote || echo 'stage') || die 'This project is not configured to use a topic stage.' @@ -65,13 +65,16 @@ fi # Perform setup if necessary. if test -n "$setup"; then echo 'Setting up the topic stage...' && + fetchurl="${fetchurl_}" && if test -z "$pushurl"; then git remote add "$remote" "$fetchurl" else git config remote."$remote".url "$fetchurl" fi && pushurl="${pushurl_}" && - git config remote."$remote".pushurl "$pushurl" && + if test "$pushurl" != "$fetchurl"; then + git config remote."$remote".pushurl "$pushurl" + fi && echo 'Remote "'"$remote"'" is now configured to push to '"$pushurl"' diff --git a/Utilities/GitSetup/setup-upstream b/Utilities/GitSetup/setup-upstream new file mode 100755 index 0000000..92ce1da --- /dev/null +++ b/Utilities/GitSetup/setup-upstream @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +#============================================================================= +# Copyright 2010-2015 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +# Run this script to set up the local Git repository to use the +# preferred upstream repository URLs. + +# Project configuration instructions: +# +# - Populate adjacent "config" file with: +# upstream.url = Preferred fetch url for upstream remote +# upstream.remote = Preferred name for upstream remote, if not "origin" + +die() { + echo 1>&2 "$@" ; exit 1 +} + +# Make sure we are inside the repository. +cd "${BASH_SOURCE%/*}" && + +# Load the project configuration. +url=$(git config -f config --get upstream.url) && +remote=$(git config -f config --get upstream.remote || + echo 'origin') || +die 'This project is not configured to use a preferred upstream repository.' + +# Get current upstream URLs. +fetchurl=$(git config --get remote."$remote".url || echo '') && +pushurl=$(git config --get remote."$remote".pushurl || echo '') && + +if test "$fetchurl" = "$url"; then + echo 'Remote "'"$remote"'" already uses recommended upstream repository.' + exit 0 +fi + +upstream_recommend=' +We recommended configuring the "'"$remote"'" remote to fetch from upstream at + + '"$url"' +' + +# Tell user about current configuration. +if test -n "$fetchurl"; then + echo 'Remote "'"$remote"'" is currently configured to fetch from + + '"$fetchurl"' +' && + if test -n "$pushurl"; then + echo 'and push to + + '"$pushurl" + fi && + echo "$upstream_recommend" && + if test -n "$pushurl"; then + echo 'and to never push to it directly. +' + fi && + + read -ep 'Reconfigure "'"$remote"'" remote as recommended? [y/N]: ' ans && + if [ "$ans" == "y" ] || [ "$ans" == "Y" ]; then + setup=1 + else + setup='' + fi +else + echo 'Remote "'"$remote"'" is not yet configured.' && + echo "$upstream_recommend" && + read -ep 'Configure "'"$remote"'" remote as recommended? [Y/n]: ' ans && + if [ "$ans" == "n" ] || [ "$ans" == "N" ]; then + exit 0 + else + setup=1 + fi +fi && + +# Perform setup if necessary. +if test -n "$setup"; then + if test -z "$fetchurl"; then + git remote add "$remote" "$url" + else + git config remote."$remote".url "$url" && + if old=$(git config --get remote."$remote".pushurl); then + git config --unset remote."$remote".pushurl || + echo 'Warning: failed to unset remote.'"$remote"'.pushurl' + fi + fi && + echo 'Remote "'"$remote"'" is now configured to fetch from + + '"$url"' +' +fi |