update-common.sh 5.29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#=============================================================================
# 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.
#=============================================================================

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
########################################################################
# 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.
34
35
#   shortlog
#       Optional.  Set to 'true' to get a shortlog in the commit message.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#
# 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 () {
51
    git archive --worktree-attributes --prefix="$name-reduced/" HEAD -- $paths | \
52
53
54
55
56
57
58
59
60
61
62
63
        tar -C "$extractdir" -x
}

die () {
    echo >&2 "$@"
    exit 1
}

warn () {
    echo >&2 "warning: $@"
}

64
readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
65
66
readonly basehash_regex="$name $regex_date ([0-9a-f]*)"
readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )"
67
readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )"
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
########################################################################
# 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"
84
readonly do_shortlog="${shortlog-false}"
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

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
104
    find . -type d -empty -delete
105
106
107
108
109
110
111
112
113
114
115
    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 )"
116
117
118
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" )"
119
120
121
122
123
124
125
126
127
128
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
129
130
131
132
133
134
extract_source || \
    die "failed to extract source"
popd

[ -d "$extractdir/$name-reduced" ] || \
    die "expected directory to extract does not exist"
135
readonly commit_summary="$name $upstream_date ($upstream_hash_short)"
136
137
138
139

# Commit the subset
pushd "$extractdir"
mv -v "$name-reduced/"* .
Ben Boeckel's avatar
Ben Boeckel committed
140
rmdir "$name-reduced/"
141
git add -A .
142
git commit -n --author="$ownership" --date="$upstream_datetime" -F - <<-EOF
143
144
145
146
147
148
$commit_summary

Code extracted from:

    $repo

149
at commit $upstream_hash ($tag).$commit_shortlog
150
EOF
151
git branch -f "upstream-$name"
152
153
154
popd

# Merge the subset into this repository
155
if [ -n "$basehash" ]; then
156
    git merge --log -s recursive "-Xsubtree=$subtree/" --no-commit "upstream-$name"
157
else
158
    git fetch "$extractdir" "upstream-$name:upstream-$name"
159
    git merge --log -s ours --no-commit "upstream-$name"
160
    git read-tree -u --prefix="$subtree/" "upstream-$name"
161
fi
162
git commit --no-edit
163
git branch -d "upstream-$name"