blob: aab3de4fa2b131366a79c5ad25d5f7276e47fef0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
#!/bin/bash
# script to help rebase trees of branches
# Git configuration
# -----------------
# rebasepp.start-commit
# Required.
# Attemps to rebase all branches child of this commit.
# rebasepp.rebase-to
# Required.
# Rebase the branches on this commit (usually origin/master)
# rebasepp.remote
# Optional.
# Attempt to push to this remote if the upstream is set to it
# rebasepp.filter
# Optional.
# "grep -v" filter applied to the branch names. Allows to
# exclude some branches.
# rebasepp.custom-script
# Optional.
# Script to source for customizations.
#
# Custom script
# -------------
# The script is sourced (shell). The current directory will be
# the git root.
# Environment passes
# COMPILE
# yes/no/full
# REBASE_TO
# rebasepp.rebase-to option
#
# Currently you can define a post_process function that will be called
# if the rebase is successful.
# The name of the branch will be passed as first argument.
error() {
echo "$*" >&2
exit 1
}
# git remove where to push our branches
REMOTE_PUSH="$(git config rebasepp.remote)"
FILTER="$(git config rebasepp.filter)"
CUSTOM_SCRIPT="$(git config rebasepp.custom-script)"
set -e
REBASE_TO="$(git config rebasepp.rebase-to)" || error "rebase-to not configured"
START_COMMIT="$(git config rebasepp.start-commit)" || error "start-commit not configured"
export REBASE_TO
cd "$(git rev-parse --show-toplevel)"
if [ -n "$FILTER" ]; then
filter() {
exec grep -v "$FILTER"
}
else
filter() {
cat
}
fi
post_process() {
:
}
if [ -n "$CUSTOM_SCRIPT" ]; then
test -r "$CUSTOM_SCRIPT" || error "Cannot read $CUSTOM_SCRIPT"
source "$CUSTOM_SCRIPT"
fi
get_id() {
git rev-parse --revs-only "refs/$1" --
}
COMPILE=${COMPILE:=no}
export COMPILE
case $COMPILE in
yes | full | no )
;;
* )
error "$COMPILE option not supported"
;;
esac
failed=''
failed_compile=''
processed=''
declare -A commits
build_it() {
make -j
}
try_compile() {
local last_failed=''
if test "$COMPILE" = "no"; then
return
fi
echo "processed:$processed"
echo "failed:$failed_compile"
echo "compiling $branch ..."
if test $COMPILE = full; then
for commit in $(git rev-list ${REBASE_TO}..$branch --reverse); do
echo "checking branch $branch commit $commit"
git checkout $commit &> /dev/null
if [ "${commits[$commit]}" = "" ]; then
if ! build_it &> compile_err_$branch.txt; then
commits[$commit]='no'
else
commits[$commit]='yes'
fi
fi
if [ "${commits[$commit]}" = "no" ]; then
failed_compile+="
$branch:$commit"
last_failed='+'
else
rm -f compile_err_$branch.txt
last_failed=''
fi
done
failed_compile+="$last_failed"
else
if ! build_it &> compile_err_$branch.txt; then
failed_compile+="
$branch"
else
rm -f compile_err_$branch.txt
fi
fi
}
all_branches() {
git show-ref --heads | perl -ne 'print $1 if m, refs/heads/(.*)$,s'
}
# get remote based on branch
branch_get_remote() {
local branch="$1"
{
git config "branch.${branch}.pushRemote" || \
git config "remote.pushDefault" || \
git config "branch.${branch}.remote";
} 2> /dev/null
}
branch_need_push() {
local branch="$1" remote
if [ -n "$REMOTE_PUSH" ]; then
# check that the upstream for this branch is our specified remote
remote=$(branch_get_remote "$branch") && [ "$REMOTE_PUSH" = "$remote" ] && {
remote=$(get_id "remotes/$REMOTE_PUSH/$branch" 2> /dev/null) && {
if [ "$remote" != "" -a "$(get_id heads/$branch)" != "$remote" ]; then
return 0
fi
}
}
fi
return 1
}
for branch in $(git branch --contains "$START_COMMIT" --no-color | \
sed 's,^..,,' | filter | LANG=C sort)
do
# exclude invalid branches (ie when we checked out a commit id)
if ! get_id "heads/$branch" &> /dev/null; then
continue
fi
# check if already in sync (so no need to checkout)
if ! branch_need_push "$branch" && test "$COMPILE" = no -a "$(git rev-list "heads/$branch..${REBASE_TO}" | wc -l)" = 0; then
processed+=" $branch"
continue
fi
# try to rebase on top of specified branch
git checkout "$branch"
if git rebase ${REBASE_TO}; then
post_process "$branch"
# if there is a remote on the git remote specified push to it
if branch_need_push "$branch"; then
echo "Pushing branch $branch ..."
git push -f
fi
try_compile
else
failed+=" $branch"
git rebase --abort
fi
processed+=" $branch"
done
if [ "$failed_compile" != "" ]; then
echo "FAILED TO COMPILE:$failed_compile"
fi
if [ "$failed" != "" ]; then
echo "FAILED BRANCHES:$failed"
exit 1
else
echo "All branches are in sync"
fi
|