Merge topic 'add_setup_for_development'

e91401ac Enable SetupForDevelopment in VTK-m
569655c4 Add autostash command flag to git-gitlab-sync
0f171de1 Add gitlab-sync command to ease updating local branches after reformats
c5d20ef7 Merge branch 'upstream-GitSetup' into add_setup_for_development
cc537c70 GitSetup 2016-12-13 (cd5ada6d)
7736f950 Add the update scripts needed to import GitSetup
793b5cf9 CONTRIBUTING guide now covers reformatting and revising commits

Acked-by: Brad King <brad.king@kitware.com>
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !792
This commit is contained in:
Robert Maynard 2017-06-08 15:12:31 -04:00 committed by Brad King
commit ca44123992
17 changed files with 1423 additions and 6 deletions

@ -26,7 +26,15 @@ Before you begin, perform initial setup:
$ cd vtk-m
The main repository will be configured as your `origin` remote.
4. (Optional but highly recommended.)
4. Run the [developer setup script] to prepare your VTK-m work tree and
create Git command aliases used below:
$ ./Utilities/SetupForDevelopment.sh
This will prompt for your GitLab user name and configure a remote
called `gitlab` to refer to it.
5. (Optional but highly recommended.)
[Register](https://open.cdash.org/register.php) with the VTK-m project
on Kitware's CDash instance to better know how your code performs in
regression tests. After registering and signing in, click on
@ -50,6 +58,7 @@ Our collaboration workflow consists of three main steps:
* [Share a Topic](#share-a-topic)
* [Create a Merge Request](#create-a-merge-request)
* [Review a Merge Request](#review-a-merge-request)
* [Reformat a Topic](#reformat-a-topic)
* [Revise a Topic](#revise-a-topic)
3. Integrate Changes:
@ -142,11 +151,13 @@ signed in for [GitLab Access][] and created your fork by visiting the main
2. Push commits in your topic branch to your fork in GitLab:
$ git push gitlab HEAD
$ git gitlab-push
Notes:
* If you are revising a previously pushed topic and have rewritten the
topic history, add `-f` or `--force` to overwrite the destination.
* The `gitlab-push` script also pushes the `master` branch to your
fork in GitLab to keep it in sync with the upstream `master`.
The output will include a link to the topic branch in your fork in GitLab
and a link to a page for creating a Merge Request.
@ -341,12 +352,47 @@ Builder names always follow this pattern:
* feature: alphabetical list of features enabled for the build
Reformat a Topic
----------------
The "Kitware Robot" automatically performs basic code formatting on the commits
and adds a comment acknowledging or rejecting a merge request based on the
format. You may request "Kitware Robot" to automatically reformat the
remote copy of your branch by issuing the command:
Do: reformat
This reformatting of the topic rewrites the commits to fix the formatting
errors, and causes the version on the developers machine to differ from
version on the gitlab server. To resolve this issue you must update
the local version to match the reformatted one on the server if you wish
to extend or revise the topic.
1. Checkout the topic if it is not your current branch:
$ git checkout my-topic
2. Get the new version from gitlab
$ git gitlab-sync -f
If you do not wish to have the "Kitware Robot" automatically reformat your
branch you can do so manually by running [clang-format][https://clang.llvm.org/docs/ClangFormat.html]
manually on each commit of your branch. This must be done by [revising each commit](#revise-a-topic)
not as new commits onto the end of the branch.
Revise a Topic
--------------
If a topic is approved during GitLab review, skip to the
[next step](#merge-a-topic). Otherwise, revise the topic
and push it back to GitLab for another review as follows:
Revising a topic is a special way to modify the commits within a topic. Normally
during a review of a merge request a developer will resolve issues brought
up during review by adding more commits to the topic. While this is sufficient
for most issues, some issues can only be resolved by rewriting the history
of the topic.
If a reviewer has asked explicitly for certain commits to be rewritten, you will
need to revise the commits and force push it back to GitLab for another review.
To revise a topic for another review as follows:
1. Checkout the topic if it is not your current branch:
@ -359,7 +405,14 @@ and push it back to GitLab for another review as follows:
(Substitute the correct number of commits back, as low as `1`.)
Follow Git's interactive instructions.
3. Return to the [above step](#share-a-topic) to share the revised topic.
3. Push commits in your topic branch to your fork in GitLab:
$ git gitlab-push -f
Notes:
* You need to add `-f` or `--force` to overwrite the destination as you
are revising a previously pushed topic and have rewritten the
topic history.
Merge a Topic
-------------

7
Utilities/GitSetup/.gitattributes vendored Normal file

@ -0,0 +1,7 @@
.git* export-ignore
.gitattributes -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

202
Utilities/GitSetup/LICENSE Normal file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

@ -0,0 +1,5 @@
Kitware Local Git Setup Scripts
Copyright 2010-2012 Kitware, Inc.
This product includes software developed at Kitware, Inc.
(http://www.kitware.com/).

87
Utilities/GitSetup/README Normal file

@ -0,0 +1,87 @@
Kitware Local Git Setup Scripts
Introduction
------------
This is a collection of local Git development setup scripts meant for
inclusion in project source trees to aid their development workflow.
Project-specific information needed by the scripts may be configured
in a "config" file added next to them in the project.
Import
------
A project may import these scripts into their source tree by
initializing a subtree merge. Bring up a Git prompt and set the
current working directory inside a clone of the target project.
Fetch the "setup" branch from the GitSetup repository:
$ git fetch ../GitSetup setup:setup
Prepare to merge the branch but place the content in a subdirectory.
Any prefix (with trailing '/') may be chosen so long as it is used
consistently within a project through the rest of these instructions:
$ git merge -s ours --no-commit setup
$ git read-tree -u --prefix=Utilities/GitSetup/ setup
Commit the merge with an informative message:
$ git commit
------------------------------------------------------------------------
Merge branch 'setup'
Add Utilities/GitSetup/ directory using subtree merge from
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
-------------
Read the "Project configuration instructions" comment in each script.
Add a "config" file next to the scripts with desired configuration
(optionally copy and modify "config.sample"). For example, to
configure the "setup-hooks" script:
$ git config -f Utilities/GitSetup/config hooks.url "$url"
where "$url" is the project repository publishing the "hooks" branch.
When finished, add and commit the configuration file:
$ git add Utilities/GitSetup/config
$ git commit
Update
------
A project may update these scripts from the GitSetup repository.
Bring up a Git prompt and set the current working directory inside a
clone of the target project. Fetch the "setup" branch from the
GitSetup repository:
$ git fetch ../GitSetup setup:setup
Merge the "setup" branch into the subtree:
$ git merge -X subtree=Utilities/GitSetup setup
where "Utilities/GitSetup" is the same prefix used during the import
setup, but without a trailing '/'.
License
-------
Distributed under the Apache License 2.0.
See LICENSE and NOTICE for details.

10
Utilities/GitSetup/config Normal file

@ -0,0 +1,10 @@
[hooks]
url = https://gitlab.kitware.com/utils/gitsetup.git
[upstream]
url = https://gitlab.kitware.com/vtk/vtk-m.git
[gitlab]
host = gitlab.kitware.com
group-path = vtk
group-name = VTK
project-path = vtk-m
project-name = VTK-m

@ -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

@ -0,0 +1,135 @@
#!/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 changed without actually updating
--autostash
automatically stash/stash pop before and after
'
OPTIONS_SPEC=
SUBDIRECTORY_OK=Yes
. "$(git --exec-path)/git-sh-setup"
egrep-q() {
egrep "$@" >/dev/null 2>/dev/null
}
# Load the project configuration.
require_work_tree_exists
state_dir="$GIT_DIR"/gitlab-sync
#-----------------------------------------------------------------------------
remote=''
autostash="$(git config --bool gitlab.sync.autostash || echo false)"
dry_run=false
# Parse the command line options.
while test $# != 0; do
case "$1" in
--autostash) autostash=true ;;
--no-autostash) autostash=false ;;
--dry-run) dry_run=true ;;
--) shift; break ;;
-*) usage ;;
*) test -z "$remote" || usage ; remote="$1" ;;
esac
shift
done
test $# = 0 || usage
# Default remote.
test -n "$remote" || remote="gitlab"
# 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 'You cant sync the master branch, please checkout the correct a branch with:
git checkout <branch>'
fi
#-----------------------------------------------------------------------------
apply_autostash () {
if test -f "$state_dir/autostash"
then
stash_sha1=$(cat "$state_dir/autostash")
if git stash apply $stash_sha1 2>&1 >/dev/null
then
gettext 'Applied autostash.'
else
git stash store -m "autostash" -q $stash_sha1 ||
die "$(eval_gettext "Cannot store \$stash_sha1")"
gettext 'Applying autostash resulted in conflicts.
Your changes are safe in the stash.
You can run "git stash pop" or "git stash drop" at any time.
'
fi
fi
}
finish_sync () {
apply_autostash &&
{ git gc --auto || true; } &&
rm -rf "$state_dir"
}
#-----------------------------------------------------------------------------
if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
then
gettext 'trying to stash local changes' &&
stash_sha1=$(git stash create "autostash") ||
die "$(gettext 'Cannot autostash')"
mkdir -p "$state_dir" &&
echo $stash_sha1 >"$state_dir/autostash" &&
stash_abbrev=$(git rev-parse --short $stash_sha1) &&
echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
git reset --hard
fi
require_clean_work_tree "sync" "$(gettext "Error syncing \
We are trying to overwrite all local changes on this branch with the version on \
gitlab. Before you do this make sure to stash your changes or commit these \
changes to a different branch.")"
#-----------------------------------------------------------------------------
fetch_stdout=$(git fetch "$remote" $topic); fetch_exit=$?
gettext "$fetch_stdout"
if [ $fetch_exit -eq 0 ]
then
if test "$dry_run" = true
then
reset_stdout=$(git diff --color HEAD..FETCH_HEAD); fetch_exit=$?
gettext "$reset_stdout"
else
reset_stdout=$(git reset --hard FETCH_HEAD); fetch_exit=$?
gettext "$reset_stdout"
fi
fi
finish_sync
# Reproduce the push exit code.
exit $fetch_exit

140
Utilities/GitSetup/setup-gitlab Executable file

@ -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

64
Utilities/GitSetup/setup-hooks Executable file

@ -0,0 +1,64 @@
#!/usr/bin/env bash
#=============================================================================
# Copyright 2010-2012 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 local Git hooks for this project.
# Project configuration instructions:
#
# - Publish a "hooks" branch in the project repository such that
# clones will have "refs/remotes/origin/hooks".
#
# - Populate adjacent "config" file with:
# hooks.url = Repository URL publishing "hooks" branch
# hooks.branch = Repository branch instead of "hooks"
egrep-q() {
egrep "$@" >/dev/null 2>/dev/null
}
die() {
echo 1>&2 "$@" ; exit 1
}
# Make sure we are inside the repository.
cd "${BASH_SOURCE%/*}" &&
# Select a hooks branch.
if url=$(git config --get hooks.url); then
# Fetch hooks from locally configured repository.
branch=$(git config hooks.branch || echo hooks)
elif git for-each-ref refs/remotes/origin/hooks 2>/dev/null |
egrep-q 'refs/remotes/origin/hooks$'; then
# Use hooks cloned from origin.
url=.. && branch=remotes/origin/hooks
elif url=$(git config -f config --get hooks.url); then
# Fetch hooks from project-configured repository.
branch=$(git config -f config hooks.branch || echo hooks)
else
die 'This project is not configured to install local hooks.'
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.'
fi &&
git fetch -q "$url" "$branch" &&
git reset -q --hard FETCH_HEAD || die 'Failed to install hooks'

111
Utilities/GitSetup/setup-ssh Executable file

@ -0,0 +1,111 @@
#!/usr/bin/env bash
#=============================================================================
# Copyright 2010-2012 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 ssh push access to the repository host.
# Project configuration instructions:
#
# - Populate adjacent "config" file with:
# ssh.host = Repository host name
# ssh.user = Username on host, if not "git"
# ssh.key = Local ssh key name
# ssh.request-url = Web page URL to request ssh access
egrep-q() {
egrep "$@" >/dev/null 2>/dev/null
}
die() {
echo 1>&2 "$@" ; exit 1
}
# Make sure we are inside the repository.
cd "${BASH_SOURCE%/*}" &&
# Load the project configuration.
host=$(git config -f config --get ssh.host) &&
user=$(git config -f config --get ssh.user || echo git) &&
key=$(git config -f config --get ssh.key) &&
request_url=$(git config -f config --get ssh.request-url) ||
die 'This project is not configured for ssh push access.'
# Check for existing configuration.
if test -r ~/.ssh/config &&
egrep-q 'Host[= ]'"${host//\./\\.}" ~/.ssh/config; then
echo 'Host "'"$host"'" is already in ~/.ssh/config' &&
setup= &&
question='Test'
else
echo 'Host "'"$host"'" not found in ~/.ssh/config' &&
setup=1 &&
question='Setup and test'
fi &&
# Ask the user whether to make changes.
echo '' &&
read -ep "${question} push access by ssh to $user@$host? [y/N]: " access &&
if test "$access" != "y" -a "$access" != "Y"; then
exit 0
fi &&
# Setup host configuration if necessary.
if test -n "$setup"; then
if ! test -d ~/.ssh; then
mkdir -p ~/.ssh &&
chmod 700 ~/.ssh
fi &&
if ! test -f ~/.ssh/config; then
touch ~/.ssh/config &&
chmod 600 ~/.ssh/config
fi &&
ssh_config='Host='"$host"'
IdentityFile ~/.ssh/'"$key" &&
echo "Adding to ~/.ssh/config:
$ssh_config
" &&
echo "$ssh_config" >> ~/.ssh/config &&
if ! test -e ~/.ssh/"$key"; then
if test -f ~/.ssh/id_rsa; then
# Take care of the common case.
ln -s id_rsa ~/.ssh/"$key"
echo '
Assuming ~/.ssh/id_rsa is the private key corresponding to the public key for
'"$user@$host"'
If this is incorrect place private key at "~/.ssh/'"$key"'".'
else
echo '
Place the private key corresponding to the public key registered for
'"$user@$host"'
at "~/.ssh/'"$key"'".'
fi
read -e -n 1 -p 'Press any key to continue...'
fi
fi || exit 1
# Test access configuration.
echo 'Testing ssh push access to "'"$user@$host"'"...' &&
if ! ssh "$user@$host" info; then
die 'No ssh push access to "'"$user@$host"'". You may need to request access at
'"$request_url"'
'
fi

104
Utilities/GitSetup/setup-upstream Executable file

@ -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

39
Utilities/GitSetup/setup-user Executable file

@ -0,0 +1,39 @@
#!/usr/bin/env bash
#=============================================================================
# Copyright 2010-2012 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 configure Git user info in this repository.
# Project configuration instructions: NONE
for (( ; ; )); do
user_name=$(git config user.name || echo '') &&
user_email=$(git config user.email || echo '') &&
if test -n "$user_name" -a -n "$user_email"; then
echo 'Your commits will record as Author:
'"$user_name <$user_email>"'
' &&
read -ep 'Is the author name and email address above correct? [Y/n] ' correct &&
if test "$correct" != "n" -a "$correct" != "N"; then
break
fi
fi &&
read -ep 'Enter your full name e.g. "John Doe": ' name &&
read -ep 'Enter your email address e.g. "john@gmail.com": ' email &&
git config user.name "$name" &&
git config user.email "$email"
done

55
Utilities/GitSetup/tips Executable file

@ -0,0 +1,55 @@
#!/usr/bin/env bash
#=============================================================================
# Copyright 2010-2012 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.
#=============================================================================
# This script makes optional suggestions for working with Git.
# Project configuration instructions: NONE
egrep-q() {
egrep "$@" >/dev/null 2>/dev/null
}
# Suggest color configuration.
if test -z "$(git config --get color.ui)"; then
echo '
One may enable color output from Git commands with
git config --global color.ui auto
'
fi
# Suggest bash completion.
if ! bash -i -c 'echo $PS1' | egrep-q '__git_ps1'; then
echo '
A dynamic, informative Git shell prompt can be obtained by sourcing
the git bash-completion script in your "~/.bashrc". Set the PS1
environmental variable as suggested in the comments at the top of the
bash-completion script. You may need to install the bash-completion
package from your distribution to obtain it.
'
fi
# Suggest merge tool.
if test -z "$(git config --get merge.tool)"; then
echo '
One may configure Git to load a merge tool with
git config merge.tool <toolname>
See "git help mergetool" for more information.
'
fi

@ -0,0 +1,28 @@
#!/usr/bin/env bash
cd "${BASH_SOURCE%/*}/.." &&
Utilities/GitSetup/setup-user && echo &&
Utilities/GitSetup/setup-hooks && echo &&
(Utilities/GitSetup/setup-upstream ||
echo 'Failed to setup origin. Run this again to retry.') && echo &&
(Utilities/GitSetup/setup-gitlab ||
echo 'Failed to setup GitLab. Run this again to retry.') && echo &&
Utilities/GitSetup/tips
echo "Setting up useful Git aliases..." &&
# Rebase master by default
git config rebase.stat true
git config branch.master.rebase true
# General aliases that could be global
git config alias.pullall '!bash -c "git pull && git submodule update --init"' &&
git config alias.prepush 'log --graph --stat origin/master..' &&
# Alias to push the current topic branch to GitLab
git config alias.gitlab-push '!bash Utilities/GitSetup/git-gitlab-push' &&
echo "Set up git gitlab-push" &&
git config alias.gitlab-sync '!bash Utilities/GitSetup/git-gitlab-sync' &&
echo "Set up git gitlab-sync" &&
true

31
Utilities/update-gitsetup.bash Executable file

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e
set -x
shopt -s dotglob
readonly name="GitSetup"
readonly ownership="GitSetup Upstream <kwrobot@kitware.com>"
readonly subtree="Utilities/GitSetup"
readonly repo="https://gitlab.kitware.com/utils/gitsetup.git"
readonly tag="setup"
readonly shortlog=false
readonly paths="
.gitattributes
LICENSE
NOTICE
README
git-gitlab-push
setup-gitlab
setup-hooks
setup-ssh
setup-upstream
setup-user
tips
"
extract_source () {
git_archive
}
. "${BASH_SOURCE%/*}/update-third-party.bash"

@ -0,0 +1,169 @@
#=============================================================================
# Copyright 2015-2016 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.
#=============================================================================
########################################################################
# Script for updating third party packages.
#
# This script should be sourced in a project-specific script which sets
# the following variables:
#
# name
# The name of the project.
# ownership
# A git author name/email for the commits.
# subtree
# The location of the thirdparty package within the main source
# tree.
# repo
# The git repository to use as upstream.
# tag
# The tag, branch or commit hash to use for upstream.
# shortlog
# Optional. Set to 'true' to get a shortlog in the commit message.
#
# Additionally, an "extract_source" function must be defined. It will be
# run within the checkout of the project on the requested tag. It should
# should place the desired tree into $extractdir/$name-reduced. This
# directory will be used as the newest commit for the project.
#
# For convenience, the function may use the "git_archive" function which
# does a standard "git archive" extraction using the (optional) "paths"
# variable to only extract a subset of the source tree.
########################################################################
########################################################################
# Utility functions
########################################################################
git_archive () {
git archive --worktree-attributes --prefix="$name-reduced/" HEAD -- $paths | \
tar -C "$extractdir" -x
}
die () {
echo >&2 "$@"
exit 1
}
warn () {
echo >&2 "warning: $@"
}
readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
readonly basehash_regex="$name $regex_date ([0-9a-f]*)"
readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )"
readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )"
########################################################################
# Sanity checking
########################################################################
[ -n "$name" ] || \
die "'name' is empty"
[ -n "$ownership" ] || \
die "'ownership' is empty"
[ -n "$subtree" ] || \
die "'subtree' is empty"
[ -n "$repo" ] || \
die "'repo' is empty"
[ -n "$tag" ] || \
die "'tag' is empty"
[ -n "$basehash" ] || \
warn "'basehash' is empty; performing initial import"
readonly do_shortlog="${shortlog-false}"
readonly workdir="$PWD/work"
readonly upstreamdir="$workdir/upstream"
readonly extractdir="$workdir/extract"
[ -d "$workdir" ] && \
die "error: workdir '$workdir' already exists"
trap "rm -rf '$workdir'" EXIT
# Get upstream
git clone "$repo" "$upstreamdir"
if [ -n "$basehash" ]; then
# Use the existing package's history
git worktree add "$extractdir" "$basehash"
# Clear out the working tree
pushd "$extractdir"
git ls-files | xargs rm -v
find . -type d -empty -delete
popd
else
# Create a repo to hold this package's history
mkdir -p "$extractdir"
git -C "$extractdir" init
fi
# Extract the subset of upstream we care about
pushd "$upstreamdir"
git checkout "$tag"
readonly upstream_hash="$( git rev-parse HEAD )"
readonly upstream_hash_short="$( git rev-parse --short=8 "$upstream_hash" )"
readonly upstream_datetime="$( git rev-list "$upstream_hash" --format='%ci' -n 1 | grep -e "^$regex_date" )"
readonly upstream_date="$( echo "$upstream_datetime" | grep -o -e "$regex_date" )"
if $do_shortlog && [ -n "$basehash" ]; then
readonly commit_shortlog="
Upstream Shortlog
-----------------
$( git shortlog --no-merges --abbrev=8 --format='%h %s' "$upstream_old_short".."$upstream_hash" )"
else
readonly commit_shortlog=""
fi
extract_source || \
die "failed to extract source"
popd
[ -d "$extractdir/$name-reduced" ] || \
die "expected directory to extract does not exist"
readonly commit_summary="$name $upstream_date ($upstream_hash_short)"
# Commit the subset
pushd "$extractdir"
mv -v "$name-reduced/"* .
rmdir "$name-reduced/"
git add -A .
git commit -n --author="$ownership" --date="$upstream_datetime" -F - <<-EOF
$commit_summary
Code extracted from:
$repo
at commit $upstream_hash ($tag).$commit_shortlog
EOF
git branch -f "upstream-$name"
popd
# Merge the subset into this repository
if [ -n "$basehash" ]; then
git merge --log -s recursive "-Xsubtree=$subtree/" --no-commit "upstream-$name"
else
unrelated_histories_flag=""
if git merge --help | grep -q -e allow-unrelated-histories; then
unrelated_histories_flag="--allow-unrelated-histories "
fi
readonly unrelated_histories_flag
git fetch "$extractdir" "upstream-$name:upstream-$name"
git merge --log -s ours --no-commit $unrelated_histories_flag "upstream-$name"
git read-tree -u --prefix="$subtree/" "upstream-$name"
fi
git commit --no-edit
git branch -d "upstream-$name"