-
Notifications
You must be signed in to change notification settings - Fork 9
/
cfbot_patchburner_chroot_ctl.sh
executable file
·186 lines (164 loc) · 5.05 KB
/
cfbot_patchburner_chroot_ctl.sh
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
#!/bin/sh
#
# This script applies patches inside a chroot. As the Linux chroot man page
# surprisingly admits, it'd be better to use FreeBSD for this purpose, but here
# we go.
#
# TODO: Figure out how to deal with the fact that chroot requires privs
# TODO: Figure out how to run script without network access
# TODO: Figure out how to limit script run time
set -e
TEMPLATE_DIR=patchburner_template
CHROOT_DIR=patchburner_chroot
RUNAS_USER=$USER
usage()
{
echo "Usage: $1 init|create|apply|destroy"
echo
echo "init-template -- create 'patchburner_template'"
echo
echo "create -- create a new chroot under 'patchburner'"
echo "apply -- apply all the patches found in patchburner/work/patches'"
echo "destroy -- destroy 'patchburner' if it exists"
echo
echo "template-repo-patch -- report path of template git repo"
echo "burner-patch-path -- report path where patches should be placed"
echo "burner-repo-path -- report path of burner git repo"
exit 1
}
init_template()
{
# This is just a clean checkout of the git repo, which cfbot will keep
# updated, and we'll copy whever we need a throw-away copy to apply patches
# to. This just avoids having to clone it every time, which would suck.
# You should only need to init once.
mkdir $TEMPLATE_DIR
mkdir $TEMPLATE_DIR/work
git clone git://git.postgresql.org/git/postgresql.git $TEMPLATE_DIR/work/postgresql
}
destroy_patchburner_if_exists()
{
rm -fr $CHROOT_DIR
}
create_patchburner()
{
# Copy the template to get a clean up-to-date repo.
cp -r $TEMPLATE_DIR $CHROOT_DIR
# Things we need to be able to apply patches in our throw-away chroot:
#
# * sh
# * patch (must be GNU patch)
# * tar
# * unzip
# * gzip
# * gunzip
# * find
# * sort
#
# We copy these from the OS root ever time rather than using the template,
# to pick up bugfixes.
case "`uname`" in
Linux*)
# Copy the minimal set of bits and pieces from from Debian 10 layout.
mkdir -p $CHROOT_DIR/bin $CHROOT_DIR/usr/bin
mkdir -p $CHROOT_DIR/lib64 $CHROOT_DIR/lib/x86_64-linux-gnu
for bin in sh dash ; do
cp /bin/$bin $CHROOT_DIR//bin/
done
for bin in cat patch unzip git gzip gunzip sed tar find sort ; do
cp /usr/bin/$bin $CHROOT_DIR/usr/bin/
done
for lib in libbz2.so libacl.so libselinux.so libc.so libm.so libattr.so libpcre.so libpcre2-8.so libdl.so libpthread.so libz.so; do
cp /lib/x86_64-linux-gnu/$lib* $CHROOT_DIR/lib/x86_64-linux-gnu/
done
cp /lib64/ld-linux-x86-64.so* $CHROOT_DIR/lib64/
;;
*)
echo "I don't know what operating system this is."
exit 1
;;
esac
# "git sendmail" uses /dev/null internally, so we need to have a /dev
# directory. We clean the file up afterwards, so it's not a big deal that
# it's not actually a special device
mkdir $CHROOT_DIR/dev
touch $CHROOT_DIR/dev/null
# create the patching script
mkdir $CHROOT_DIR/work/patches
cat > $CHROOT_DIR/work/apply-patches.sh <<'EOF'
#!/bin/sh
#
# apply all patches found in /work/patches
set -e
# unpack and zip archives, tarballs etc
cd /work/patches
for f in $(find . -name '*.tgz' -o -name '*.tar.gz' -o -name '*.tar.bz2') ; do
echo "=== expanding $f"
tar xzvf $f
done
for f in $(find . -name '*.gz') ; do
echo "=== expanding $f"
gunzip $f
done
for f in $(find . -name '*.zip') ; do
echo "=== expanding $f"
unzip $f
done
# now apply all .patch and .diff files
cd /work/postgresql
# But first set up the git user
git config user.name "Commitfest Bot"
git config user.email "cfbot@cputube.org"
for f in $(cd /work/patches && find . -name '*.patch' -o -name '*.diff' | sort) ; do
echo "=== applying patch $f"
git mailinfo ../msg ../patch < "/work/patches/$f" > ../info
# Clean out /dev/null in case git mailinfo wrote something to it
: > /dev/null
NAME=$(sed -n -e 's/^Author: //p' ../info)
EMAIL=$(sed -n -e 's/^Email: //p' ../info)
SUBJECT=$(sed -n -e 's/^Subject: //p' ../info)
DATE=$(sed -n -e 's/^Date: //p' ../info)
MESSAGE="$(cat ../msg)"
MESSAGE="${SUBJECT:-"[PATCH]: $f"}${MESSAGE:+
}${MESSAGE}"
patch --no-backup-if-mismatch -p1 -V none -f < "/work/patches/$f"
git add .
git commit -m "$MESSAGE" --author="${NAME:-Commitfest Bot} <${EMAIL:-cfbot@cputube.org}>" --date="${DATE:-now}" --allow-empty
done
EOF
chmod 775 $CHROOT_DIR/work/apply-patches.sh
chown -R $RUNAS_USER:$RUNAS_USER $CHROOT_DIR/work
}
apply_patches_in_patchburner()
{
sudo chroot --userspec=$RUNAS_USER $CHROOT_DIR /work/apply-patches.sh
rm -rf $CHROOT_DIR/work/postgresql/.git/hooks
rm -rf $CHROOT_DIR/work/postgresql/.git/config
cp $TEMPLATE_DIR/work/postgresql/.git/config $CHROOT_DIR/work/postgresql/.git/config
}
case $1 in
init-template)
init_template
;;
create)
create_patchburner
;;
destroy)
destroy_patchburner_if_exists
;;
apply)
apply_patches_in_patchburner
;;
template-repo-path)
echo $TEMPLATE_DIR/work/postgresql
;;
burner-patch-path)
echo $CHROOT_DIR/work/patches
;;
burner-repo-path)
echo $CHROOT_DIR/work/postgresql
;;
*)
usage
;;
esac