1414# limitations under the License.
1515# =============================================================================
1616
17+ set -e
18+
19+ # Disable noise from `pre-commit` when no configuration is present on the
20+ # imported tree.
21+ export PRE_COMMIT_ALLOW_NO_CONFIG=1
22+
1723# #######################################################################
1824# Script for updating third party packages.
1925#
3339# The tag, branch or commit hash to use for upstream.
3440# shortlog
3541# Optional. Set to 'true' to get a shortlog in the commit message.
42+ # exact_tree_match
43+ # Optional. Set to 'false' to disable tree-object based matching for
44+ # previous import commit (required for projects that allow modifying
45+ # imported trees). In such cases, log-based searching is performed.
3646#
3747# Additionally, an "extract_source" function must be defined. It will be
3848# run within the checkout of the project on the requested tag. It should
6070#
6171# #######################################################################
6272
63-
64- export PRE_COMMIT_ALLOW_NO_CONFIG=1
65-
6673# #######################################################################
6774# Utility functions
6875# #######################################################################
@@ -99,12 +106,13 @@ die () {
99106}
100107
101108warn () {
102- echo >&2 " warning: $@ "
109+ echo >&2 " warning:" " $@ "
103110}
104111
105112readonly regex_date=' 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
106113readonly basehash_regex=" $name $regex_date ([0-9a-f]*)"
107- readonly toplevel_dir=" $( git rev-parse --show-toplevel ) "
114+ toplevel_dir=" $( git rev-parse --show-toplevel ) "
115+ readonly toplevel_dir
108116
109117cd " $toplevel_dir "
110118
@@ -121,17 +129,39 @@ cd "$toplevel_dir"
121129 die " 'repo' is empty"
122130[ -n " $tag " ] || \
123131 die " 'tag' is empty"
132+ [ -n " $exact_tree_match " ] || \
133+ exact_tree_match=true
124134
125135# Check for an empty destination directory on disk. By checking on disk and
126136# not in the repo it allows a library to be freshly re-inialized in a single
127137# commit rather than first deleting the old copy in one commit and adding the
128138# new copy in a separate commit.
129- if [ ! -d " $( git rev-parse --show-toplevel) /$subtree " ]; then
130- readonly basehash=" "
139+ if [ ! -d " $( git rev-parse --show-toplevel ) /$subtree " ]; then
140+ basehash=" "
141+ elif $exact_tree_match ; then
142+ # Find the tree object for the current subtree.
143+ current_tree=" $( git rev-parse " HEAD:$subtree " ) "
144+ # Search history for a commit whose subtree matches this tree object.
145+ basehash=" "
146+ # Limit candidate commits to those with expected import commit messages for efficiency.
147+ for commit in $( git rev-list --author=" $ownership " --grep=" $basehash_regex " HEAD ) ; do
148+ imported_tree=" $( git rev-parse " $commit ^{tree}" ) "
149+ # Verify the imported tree is what is currently imported. If so, we
150+ # have found the desired import commit.
151+ if [ " $imported_tree " = " $current_tree " ] && [ -n " $imported_tree " ]; then
152+ basehash=" $commit "
153+ break
154+ fi
155+ done
156+ if [ -z " $basehash " ]; then
157+ die " No previous import commit found with matching tree object for $subtree . (exact_tree_match enabled)"
158+ fi
131159else
132- readonly basehash=" $( git rev-list --author=" $ownership " --grep=" $basehash_regex " -n 1 HEAD ) "
160+ basehash=" $( git rev-list --author=" $ownership " --grep=" $basehash_regex " -n 1 HEAD ) "
133161fi
134- readonly upstream_old_short=" $( git cat-file commit " $basehash " | sed -n ' /' " $basehash_regex " ' / {s/.*(//;s/)//;p;}' | egrep ' ^[0-9a-f]+$' ) "
162+ readonly basehash
163+ upstream_old_short=" $( git cat-file commit " $basehash " | sed -n ' /' " $basehash_regex " ' / {s/.*(//;s/)//;p;}' | grep -E ' ^[0-9a-f]+$' ) "
164+ readonly upstream_old_short
135165
136166[ -n " $basehash " ] || \
137167 warn " 'basehash' is empty; performing initial import"
@@ -146,6 +176,9 @@ readonly extractdir="$workdir/extract"
146176
147177trap " rm -rf '$workdir '" EXIT
148178
179+ # Skip LFS downloading; imports should not need LFS data.
180+ export GIT_LFS_SKIP_SMUDGE=1
181+
149182# Get upstream
150183git clone --recursive " $repo " " $upstreamdir "
151184
@@ -170,20 +203,25 @@ pushd "$upstreamdir"
170203git checkout " $tag "
171204git submodule sync --recursive
172205git submodule update --recursive --init
173- readonly upstream_hash=" $( git rev-parse HEAD ) "
174- readonly upstream_hash_short=" $( git rev-parse --short=8 " $upstream_hash " ) "
175- readonly upstream_datetime=" $( git rev-list " $upstream_hash " --format=' %ci' -n 1 | grep -e " ^$regex_date " ) "
176- readonly upstream_date=" $( echo " $upstream_datetime " | grep -o -e " $regex_date " ) "
206+ upstream_hash=" $( git rev-parse HEAD ) "
207+ readonly upstream_hash
208+ upstream_hash_short=" $( git rev-parse --short=8 " $upstream_hash " ) "
209+ readonly upstream_hash_short
210+ upstream_datetime=" $( git rev-list " $upstream_hash " --format=' %ci' -n 1 | grep -e " ^$regex_date " ) "
211+ readonly upstream_datetime
212+ upstream_date=" $( echo " $upstream_datetime " | grep -o -e " $regex_date " ) "
213+ readonly upstream_date
177214if $do_shortlog && [ -n " $basehash " ]; then
178- readonly commit_shortlog="
215+ commit_shortlog="
179216
180217Upstream Shortlog
181218-----------------
182219
183220$( git shortlog --no-merges --abbrev=8 --format=' %h %s' " $upstream_old_short " .." $upstream_hash " ) "
184221else
185- readonly commit_shortlog=" "
222+ commit_shortlog=" "
186223fi
224+ readonly commit_shortlog
187225extract_source || \
188226 die " failed to extract source"
189227popd
@@ -197,7 +235,7 @@ pushd "$extractdir"
197235mv -v " $name -reduced/" * .
198236rmdir " $name -reduced/"
199237git add -A .
200- git commit --no-gpg-sign - n --author=" $ownership " --date=" $upstream_datetime " -F - << -EOF
238+ git commit -n --author=" $ownership " --date=" $upstream_datetime " -F - << -EOF
201239$commit_summary
202240
203241Code extracted from:
217255 # will fail, so use the flag by default.
218256 unrelated_histories_flag=" "
219257 if git --version | grep -q windows; then
220- unrelated_histories_flag=" --allow-unrelated-histories "
258+ unrelated_histories_flag=" --allow-unrelated-histories"
221259 elif git merge --help | grep -q -e allow-unrelated-histories; then
222- unrelated_histories_flag=" --allow-unrelated-histories "
260+ unrelated_histories_flag=" --allow-unrelated-histories"
223261 fi
224262 readonly unrelated_histories_flag
225263
0 commit comments