Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/Scripts/update-third-party.bash
3148 views
1
#=============================================================================
2
# Copyright 2015-2016 Kitware, Inc.
3
#
4
# Licensed under the Apache License, Version 2.0 (the "License");
5
# you may not use this file except in compliance with the License.
6
# You may obtain a copy of the License at
7
#
8
# http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
#=============================================================================
16
17
########################################################################
18
# Script for updating third party packages.
19
#
20
# This script should be sourced in a project-specific script which sets
21
# the following variables:
22
#
23
# name
24
# The name of the project.
25
# ownership
26
# A git author name/email for the commits.
27
# subtree
28
# The location of the third-party package within the main source
29
# tree.
30
# repo
31
# The git repository to use as upstream.
32
# tag
33
# The tag, branch or commit hash to use for upstream.
34
# shortlog
35
# Optional. Set to 'true' to get a shortlog in the commit message.
36
#
37
# Additionally, an "extract_source" function must be defined. It will be
38
# run within the checkout of the project on the requested tag. It should
39
# should place the desired tree into $extractdir/$name-reduced. This
40
# directory will be used as the newest commit for the project.
41
#
42
# For convenience, the function may use the "git_archive" function which
43
# does a standard "git archive" extraction using the (optional) "paths"
44
# variable to only extract a subset of the source tree.
45
#
46
# Dependencies
47
#
48
# To update third party packages from git repositories with submodule,
49
# you will need to install the "git-archive-all" Python package with
50
#
51
# pip install git-archive-all
52
#
53
# or install it from https://github.com/Kentzo/git-archive-all.
54
#
55
# This package installs a script named "git-archive-all" where pip
56
# installs executables. If you run pip under your user privileges (i.e.,
57
# not using "sudo"), this location may be $HOME/.local/bin. Make sure
58
# that directory is in your path so that git can find the
59
# "git-archive-all" script.
60
#
61
########################################################################
62
63
########################################################################
64
# Utility functions
65
########################################################################
66
git_archive () {
67
git archive --worktree-attributes --prefix="$name-reduced/" HEAD -- $paths | \
68
tar -C "$extractdir" -x
69
}
70
71
confirm_archive_all_exists () {
72
which git-archive-all || die "git requires an archive-all command. Please run 'pip install git-archive-all'"
73
}
74
75
git_archive_all () {
76
confirm_archive_all_exists
77
local tmptarball="temp.tar"
78
git archive-all --prefix="" "$tmptarball"
79
mkdir -p "$extractdir/$name-reduced"
80
tar -C "$extractdir/$name-reduced" -xf "$tmptarball" $paths
81
rm -f "$tmptarball"
82
}
83
84
disable_custom_gitattributes() {
85
pushd "${extractdir}/${name}-reduced"
86
# Git does not allow custom attributes in a subdirectory where we
87
# are about to merge the `.gitattributes` file, so disable them.
88
sed -i '/^\[attr\]/ {s/^/#/;}' .gitattributes
89
popd
90
}
91
92
die () {
93
echo >&2 "$@"
94
exit 1
95
}
96
97
warn () {
98
echo >&2 "warning: $@"
99
}
100
101
readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
102
readonly basehash_regex="$name $regex_date ([0-9a-f]*)"
103
readonly toplevel_dir="$( git rev-parse --show-toplevel )"
104
105
cd "$toplevel_dir"
106
107
########################################################################
108
# Sanity checking
109
########################################################################
110
[ -n "$name" ] || \
111
die "'name' is empty"
112
[ -n "$ownership" ] || \
113
die "'ownership' is empty"
114
[ -n "$subtree" ] || \
115
die "'subtree' is empty"
116
[ -n "$repo" ] || \
117
die "'repo' is empty"
118
[ -n "$tag" ] || \
119
die "'tag' is empty"
120
121
# Check for an empty destination directory on disk. By checking on disk and
122
# not in the repo it allows a library to be freshly re-initialized in a single
123
# commit rather than first deleting the old copy in one commit and adding the
124
# new copy in a separate commit.
125
if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then
126
readonly basehash=""
127
else
128
readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )"
129
fi
130
readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p;}' | egrep '^[0-9a-f]+$' )"
131
132
[ -n "$basehash" ] || \
133
warn "'basehash' is empty; performing initial import"
134
readonly do_shortlog="${shortlog-false}"
135
136
readonly workdir="$PWD/work"
137
readonly upstreamdir="$workdir/upstream"
138
readonly extractdir="$workdir/extract"
139
140
[ -d "$workdir" ] && \
141
die "error: workdir '$workdir' already exists"
142
143
trap "rm -rf '$workdir'" EXIT
144
145
# Get upstream
146
git clone --recursive "$repo" "$upstreamdir"
147
148
if [ -n "$basehash" ]; then
149
# Remove old worktrees
150
git worktree prune
151
# Use the existing package's history
152
git worktree add "$extractdir" "$basehash"
153
# Clear out the working tree
154
pushd "$extractdir"
155
git ls-files -z --recurse-submodules | xargs -0 rm -v
156
find . -type d -empty -delete
157
popd
158
else
159
# Create a repo to hold this package's history
160
mkdir -p "$extractdir"
161
git -C "$extractdir" init
162
fi
163
164
# Extract the subset of upstream we care about
165
pushd "$upstreamdir"
166
git checkout "$tag"
167
git submodule sync --recursive
168
git submodule update --recursive --init
169
readonly upstream_hash="$( git rev-parse HEAD )"
170
readonly upstream_hash_short="$( git rev-parse --short=8 "$upstream_hash" )"
171
readonly upstream_datetime="$( git rev-list "$upstream_hash" --format='%ci' -n 1 | grep -e "^$regex_date" )"
172
readonly upstream_date="$( echo "$upstream_datetime" | grep -o -e "$regex_date" )"
173
if $do_shortlog && [ -n "$basehash" ]; then
174
readonly commit_shortlog="
175
176
Upstream Shortlog
177
-----------------
178
179
$( git shortlog --no-merges --abbrev=8 --format='%h %s' "$upstream_old_short".."$upstream_hash" )"
180
else
181
readonly commit_shortlog=""
182
fi
183
extract_source || \
184
die "failed to extract source"
185
popd
186
187
[ -d "$extractdir/$name-reduced" ] || \
188
die "expected directory to extract does not exist"
189
readonly commit_summary="$name $upstream_date ($upstream_hash_short)"
190
191
# Commit the subset
192
pushd "$extractdir"
193
mv -v "$name-reduced/"* .
194
rmdir "$name-reduced/"
195
git add -A .
196
git commit -n --author="$ownership" --date="$upstream_datetime" -F - <<-EOF
197
$commit_summary
198
199
Code extracted from:
200
201
$repo
202
203
at commit $upstream_hash ($tag).$commit_shortlog
204
EOF
205
git branch -f "upstream-$name"
206
popd
207
208
# Merge the subset into this repository
209
if [ -n "$basehash" ]; then
210
git merge --log -s recursive "-Xsubtree=$subtree/" --no-commit "upstream-$name"
211
else
212
# Note: on Windows 'git merge --help' will open a browser, and the check
213
# will fail, so use the flag by default.
214
unrelated_histories_flag=""
215
if git --version | grep -q windows; then
216
unrelated_histories_flag="--allow-unrelated-histories "
217
elif git merge --help | grep -q -e allow-unrelated-histories; then
218
unrelated_histories_flag="--allow-unrelated-histories "
219
fi
220
readonly unrelated_histories_flag
221
222
git fetch "$extractdir" "+upstream-$name:upstream-$name"
223
git merge --log -s ours --no-commit $unrelated_histories_flag "upstream-$name"
224
git read-tree -u --prefix="$subtree/" "upstream-$name"
225
fi
226
git commit --no-edit
227
git branch -d "upstream-$name"
228
229