-
Notifications
You must be signed in to change notification settings - Fork 35
/
build_cached
executable file
·182 lines (151 loc) · 5.93 KB
/
build_cached
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
#!/bin/bash
MAKE=$1
SRC=$2
CACHESUBDIR=$3
# skip caching if cache folder is not set or does not exist or omd version length is too small, which would be error prone
if [ "x$BUILD_CACHE" = "x" ] || ! test -d $BUILD_CACHE/. || [ ${#OMD_VERSION} -lt 5 ]; then
$MAKE -C "$SRC" build
exit $?
fi
XXD="xxd -g 0 -u -ps -c 256"
replace_strings_in_binary() {
local FILE="$1"
local PATTERN="$2"
local REPLACEMENT="$3"
$XXD ${FILE} | tr -d '\n' > ${FILE}.hex
# Find all unique strings in FILE that contain the pattern
strings --all ${FILE} | grep ${PATTERN} | sort -u -r | \
while read OLD_STRING; do
# Create the new string with a simple bash-replacement
NEW_STRING=${OLD_STRING//${PATTERN}/${REPLACEMENT}}
# newlines will not be printed from "strings --all" so try to replace null byte termined strings and newline + null byte
for ENDING in 00 0A00; do
# Create null terminated ASCII HEX representations of the strings
OLD_STRING_HEX=$(echo -n "${OLD_STRING}" | $XXD | tr -d '\n')$ENDING
NEW_STRING_HEX=$(echo -n "${NEW_STRING}" | $XXD | tr -d '\n')$ENDING
if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then
# Pad the replacement string with null terminations so the length matches the original string
while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do
NEW_STRING_HEX="${NEW_STRING_HEX}00"
done
sed -e "s%${OLD_STRING_HEX}%${NEW_STRING_HEX}%g" -i ${FILE}.hex
else
echo "ERROR: New string '${NEW_STRING}' is longer than old string '${OLD_STRING}'. Skipping."
fi
done
# as part of a multiline string we pad with spaces
for ENDING in 0A; do
# Create null terminated ASCII HEX representations of the strings
OLD_STRING_HEX=$(echo -n "${OLD_STRING}" | $XXD | tr -d '\n')
NEW_STRING_HEX=$(echo -n "${NEW_STRING}" | $XXD | tr -d '\n')
if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then
# Pad the replacement string with spaces so the length matches the original string
while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do
NEW_STRING_HEX="${NEW_STRING_HEX}20"
done
OLD_STRING_HEX="${OLD_STRING_HEX}$ENDING"
NEW_STRING_HEX="${NEW_STRING_HEX}$ENDING"
sed -e "s%${OLD_STRING_HEX}%${NEW_STRING_HEX}%g" -i ${FILE}.hex
else
echo "ERROR: New string '${NEW_STRING}' is longer than old string '${OLD_STRING}'. Skipping."
fi
done
done
$XXD -r ${FILE}.hex ${FILE}.bin
chmod --reference ${FILE} ${FILE}.bin
mv ${FILE}.bin ${FILE}
rm ${FILE}.hex
}
replace_strings_in_ascii_file() {
local FILE="$1"
local PATTERN="$2"
local REPLACEMENT="$3"
sed -e "s%${PATTERN}%${REPLACEMENT}%g" ${FILE} > ${FILE}.tmp
chmod --reference ${FILE} ${FILE}.tmp
mv ${FILE}.tmp ${FILE}
}
BUILD_CACHE=$BUILD_CACHE/$CACHESUBDIR
mkdir -p $BUILD_CACHE
$MAKE -C "$SRC" clean >/dev/null
MD5=$(../.hashsum $SRC)
if [ "$MD5" = "" ]; then
echo "ERROR: failed to calculate package hashsum for $SRC"
exit 1
fi
CACHE_FILE="$BUILD_CACHE/${SRC}_${MD5}_v${OMD_VERSION}.tgz"
CACHE_PATTERN="$BUILD_CACHE/${SRC}_${MD5}_v*.tgz"
# cache hit - just unpack the already built package
CACHED_FILE=$(ls -1 $CACHE_PATTERN 2>/dev/null)
if [ "x$CACHED_FILE" != "x" ] && test -s "$CACHED_FILE"; then
echo "md5sum matched, trying cache from $CACHED_FILE"
tar zxf "$CACHED_FILE" || exit 1
OLD_VERSION=$(echo $CACHED_FILE | sed -e 's/.*_v\(.*\)\.tgz/\1/')
if [ ${OMD_VERSION} = ${OLD_VERSION} ] ; then
# cache file from today, no need to replace anything
touch $CACHED_FILE
exit 0
elif [ ${#OMD_VERSION} -le ${#OLD_VERSION} ] ; then
touch $CACHED_FILE
# rename files and folders
find "$SRC/" -type d | grep $OLD_VERSION | sort | \
while read FILE; do
if test -e $FILE; then
NEW_FILE=${FILE//${OLD_VERSION}/${OMD_VERSION}}
mv "$FILE" "$NEW_FILE"
fi
done
# replace strings in ascii files
grep -rlI "$OLD_VERSION" "$SRC/" | \
while read FILE; do
replace_strings_in_ascii_file "$FILE" "$OLD_VERSION" "$OMD_VERSION"
done
# replace strings in binary files
grep -rla "$OLD_VERSION" "$SRC/" | \
while read FILE; do
replace_strings_in_binary "$FILE" "$OLD_VERSION" "$OMD_VERSION"
done
# make sure we got all occurences
MISSED=$(grep -rla "$OLD_VERSION" "$SRC/")
if [ "x$MISSED" != "x" ]; then
echo "ERROR: replace did not work, files $MISSED still contains old version."
exit 1
fi
# update timestamps, so make does not rebuild everything
touch .
find "$SRC/" | \
while read FILE; do
touch -h -c -r . $FILE
done
exit 0
else
echo "cannot use $CACHED_FILE, version string $OMD_VERSION longer than $OLD_VERSION"
fi
$MAKE -C "$SRC" clean
fi
echo "no cached file found building from source and creating $CACHE_FILE"
# exclude files from before the build
EXCLUDES_FILE=$(mktemp)
find "./$SRC" -type f > $EXCLUDES_FILE
# no cache hit - rebuild package and create cache tarball
set -e
$MAKE -C "$SRC" build
set +e
# create cache file
TARBALL_TMP=$(mktemp)
set -e
tar --exclude=\*.orig --exclude-from=$EXCLUDES_FILE -czf $TARBALL_TMP "./$SRC"
rm -f "$CACHE_FILE"
rm -f $CACHE_PATTERN
mv $TARBALL_TMP "$CACHE_FILE"
set +e
echo "cache file $CACHE_FILE created"
rm $EXCLUDES_FILE
# check md5 sum
$MAKE -C "$SRC" clean >/dev/null
MD5_CHECK=$(../.hashsum $SRC)
if [ "$MD5" != "$MD5_CHECK" ]; then
echo "ERROR: make clean is broken and did not clean everything"
exit 1
fi
tar zxf "$CACHE_FILE" || exit 1
exit 0