From a0144297e59d08516e1d488a4ff9fb51284fc224 Mon Sep 17 00:00:00 2001
From: GitSetup Upstream <kwrobot@kitware.com>
Date: Tue, 13 Dec 2016 15:01:48 -0500
Subject: [PATCH] GitSetup 2016-12-13 (8af10838)

Code extracted from:

    https://gitlab.kitware.com/utils/gitsetup.git

at commit 8af1083866f06d8a65d7565367e1ca7545b9e919 (setup).
---
 .gitattributes  |   9 ---
 README          |   7 ++
 config.sample   |  10 +++
 git-gerrit-push |  21 +++---
 git-gitlab-push | 177 ++++++++++++++++++++++++++++++++++++++++++++++++
 setup-gitlab    | 140 ++++++++++++++++++++++++++++++++++++++
 setup-hooks     |   1 +
 setup-upstream  | 104 ++++++++++++++++++++++++++++
 8 files changed, 450 insertions(+), 19 deletions(-)
 delete mode 100644 .gitattributes
 create mode 100755 git-gitlab-push
 create mode 100755 setup-gitlab
 create mode 100755 setup-upstream

diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 3323f94b..00000000
--- a/.gitattributes
+++ /dev/null
@@ -1,9 +0,0 @@
-.git*            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/README b/README
index cf468fb6..2f9f1ec0 100644
--- a/README
+++ b/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/config.sample b/config.sample
index bba2382c..eeb468ba 100644
--- a/config.sample
+++ b/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/git-gerrit-push b/git-gerrit-push
index 2471490c..b46f753e 100755
--- a/git-gerrit-push
+++ b/git-gerrit-push
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 #=============================================================================
-# Copyright 2010-2012 Kitware, Inc.
+# 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.
@@ -45,25 +45,26 @@ test -n "$remote" || remote="gerrit"
 
 if test -z "$no_topic"; then
 	# Identify and validate the topic branch name.
-	topic="$(git symbolic-ref HEAD | sed -e 's|^refs/heads/||')"
-	if test "$topic" = "master"; then
+	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
-	refspecs="HEAD:refs/for/master/$topic"
+	# 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!"
+	echo 'Nothing to push!'
 	exit 0
 fi
 
-# Fetch the current upstream master branch head.
-# This helps the computation of a minimal pack to push.
-echo "Fetching $remote master"
-fetch_out=$(git fetch "$remote" master 2>&1) || die "$fetch_out"
-
 # Push.  Save output and exit code.
 echo "Pushing to $remote"
 push_stdout=$(git push --porcelain $dry_run "$remote" $refspecs); push_exit=$?
diff --git a/git-gitlab-push b/git-gitlab-push
new file mode 100755
index 00000000..768f8534
--- /dev/null
+++ b/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/setup-gitlab b/setup-gitlab
new file mode 100755
index 00000000..9c7574d1
--- /dev/null
+++ b/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/setup-hooks b/setup-hooks
index c07985ae..ca07712d 100755
--- a/setup-hooks
+++ b/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/setup-upstream b/setup-upstream
new file mode 100755
index 00000000..92ce1dae
--- /dev/null
+++ b/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
-- 
GitLab