]>
Commit | Line | Data |
---|---|---|
1f369f0c UH |
1 | # This file is supposed to be sourced by each Recipe |
2 | # that wants to use the functions contained herein | |
3 | # like so: | |
4 | # wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./functions.sh | |
5 | # . ./functions.sh | |
6 | ||
7 | # RECIPE=$(realpath "$0") | |
8 | ||
9 | # Options for apt-get to use local files rather than the system ones | |
10 | OPTIONS="-o Debug::NoLocking=1 | |
11 | -o APT::Cache-Limit=125829120 | |
12 | -o Dir::Etc::sourcelist=./sources.list | |
13 | -o Dir::State=./tmp | |
14 | -o Dir::Cache=./tmp | |
15 | -o Dir::State::status=./status | |
16 | -o Dir::Etc::sourceparts=- | |
17 | -o APT::Get::List-Cleanup=0 | |
18 | -o APT::Get::AllowUnauthenticated=1 | |
19 | -o Debug::pkgProblemResolver=true | |
20 | -o Debug::pkgDepCache::AutoInstall=true | |
21 | -o APT::Install-Recommends=0 | |
22 | -o APT::Install-Suggests=0 | |
23 | " | |
24 | ||
25 | # Either get the file from remote or from a static place. | |
26 | # critical for builds without network access like in Open Build Service | |
27 | cat_file_from_url() | |
28 | { | |
29 | cat_excludelist="wget -q $1 -O -" | |
30 | [ -e "$STATIC_FILES/${1##*/}" ] && cat_excludelist="cat $STATIC_FILES/${1##*/}" | |
31 | $cat_excludelist | |
32 | } | |
33 | ||
34 | git_pull_rebase_helper() | |
35 | { | |
36 | git reset --hard HEAD | |
37 | git pull | |
38 | } | |
39 | ||
40 | # Patch /usr to ././ in ./usr | |
41 | # to make the contents of usr/ relocateable | |
42 | # (this requires us to cd ./usr before running the application; AppRun does that) | |
43 | patch_usr() | |
44 | { | |
45 | find usr/ -type f -executable -exec sed -i -e "s|/usr|././|g" {} \; | |
46 | } | |
47 | ||
48 | # Download AppRun and make it executable | |
49 | get_apprun() | |
50 | { | |
51 | # wget -c https://github.com/probonopd/AppImageKit/releases/download/5/AppRun -O ./AppRun # 64-bit | |
52 | wget -c https://github.com/probonopd/AppImageKit/releases/download/6/AppRun_6-x86_64 -O AppRun # 64-bit | |
53 | chmod a+x AppRun | |
54 | } | |
55 | ||
56 | # Copy the library dependencies of all exectuable files in the current directory | |
57 | # (it can be beneficial to run this multiple times) | |
58 | copy_deps() | |
59 | { | |
60 | PWD=$(readlink -f .) | |
61 | FILES=$(find . -type f -executable -or -name *.so.* -or -name *.so | sort | uniq ) | |
62 | for FILE in $FILES ; do | |
63 | ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' echo '{}' >> DEPSFILE | |
64 | done | |
65 | DEPS=$(cat DEPSFILE | sort | uniq) | |
66 | for FILE in $DEPS ; do | |
67 | if [ -e $FILE ] && [[ $(readlink -f $FILE)/ != $PWD/* ]] ; then | |
68 | cp -v --parents -rfL $FILE ./ || true | |
69 | fi | |
70 | done | |
71 | rm -f DEPSFILE | |
72 | } | |
73 | ||
74 | # Move ./lib/ tree to ./usr/lib/ | |
75 | move_lib() | |
76 | { | |
77 | mkdir -p ./usr/lib ./lib && find ./lib/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib | |
78 | mkdir -p ./usr/lib ./lib64 && find ./lib64/ -exec cp -v --parents -rfL {} ./usr/ \; && rm -rf ./lib64 | |
79 | } | |
80 | ||
81 | # Delete blacklisted files | |
82 | delete_blacklisted() | |
83 | { | |
84 | BLACKLISTED_FILES=$( cat_file_from_url https://github.com/probonopd/AppImages/raw/master/excludelist | sed '/^\s*$/d' | sed '/^#.*$/d') | |
85 | echo $BLACKLISTED_FILES | |
86 | for FILE in $BLACKLISTED_FILES ; do | |
87 | FOUND=$(find . -xtype f -name "${FILE}" 2>/dev/null) | |
88 | if [ ! -z "$FOUND" ] ; then | |
89 | echo "Deleting blacklisted ${FOUND}" | |
90 | rm -f "${FOUND}" | |
91 | fi | |
92 | done | |
93 | ||
94 | # Do not bundle developer stuff | |
95 | rm -rf usr/include || true | |
96 | rm -rf usr/lib/cmake || true | |
97 | rm -rf usr/lib/pkgconfig || true | |
98 | find . -name '*.la' | xargs -i rm {} | |
99 | } | |
100 | ||
101 | # Echo highest glibc version needed by the executable files in the current directory | |
102 | glibc_needed() | |
103 | { | |
104 | find . -name *.so -or -name *.so.* -or -type f -executable -exec readelf -s '{}' 2>/dev/null \; | sed -n 's/.*@GLIBC_//p'| awk '{print $1}' | sort --version-sort | tail -n 1 | |
105 | } | |
106 | # Add desktop integration | |
107 | # Usage: get_desktopintegration name_of_desktop_file_and_exectuable | |
108 | get_desktopintegration() | |
109 | { | |
110 | REALBIN=$(grep -o "^Exec=.*" *.desktop | sed -e 's|Exec=||g' | cut -d " " -f 1 | head -n 1) | |
111 | cat_file_from_url https://raw.githubusercontent.com/probonopd/AppImageKit/master/desktopintegration > ./usr/bin/$REALBIN.wrapper | |
112 | chmod a+x ./usr/bin/$REALBIN.wrapper | |
113 | ||
114 | sed -i -e "s|^Exec=$REALBIN|Exec=$REALBIN.wrapper|g" $1.desktop | |
115 | } | |
116 | ||
117 | # Generate AppImage; this expects $ARCH, $APP and $VERSION to be set | |
118 | generate_appimage() | |
119 | { | |
120 | # if [[ "$RECIPE" == *ecipe ]] ; then | |
121 | # echo "#!/bin/bash -ex" > ./$APP.AppDir/Recipe | |
122 | # echo "# This recipe was used to generate this AppImage." >> ./$APP.AppDir/Recipe | |
123 | # echo "# See http://appimage.org for more information." >> ./$APP.AppDir/Recipe | |
124 | # echo "" >> ./$APP.AppDir/Recipe | |
125 | # cat $RECIPE >> ./$APP.AppDir/Recipe | |
126 | # fi | |
127 | # | |
128 | # Detect the architecture of what we are packaging. | |
129 | # The main binary could be a script, so let's use a .so library | |
130 | BIN=$(find . -name *.so* -type f | head -n 1) | |
131 | INFO=$(file "$BIN") | |
132 | if [ -z $ARCH ] ; then | |
133 | if [[ $INFO == *"x86-64"* ]] ; then | |
134 | ARCH=x86_64 | |
135 | elif [[ $INFO == *"i686"* ]] ; then | |
136 | ARCH=i686 | |
137 | elif [[ $INFO == *"armv6l"* ]] ; then | |
138 | ARCH=armhf | |
139 | else | |
140 | echo "Could not automatically detect the architecture." | |
141 | echo "Please set the \$ARCH environment variable." | |
142 | exit 1 | |
143 | fi | |
144 | fi | |
145 | wget -c "https://github.com/probonopd/AppImageKit/releases/download/6/AppImageAssistant_6-x86_64.AppImage" -O AppImageAssistant # (64-bit) | |
146 | chmod a+x ./AppImageAssistant | |
147 | mkdir -p ../out || true | |
148 | rm ../out/$APP"-"$VERSION"-x86_64.AppImage" 2>/dev/null || true | |
149 | ./AppImageAssistant ./$APP.AppDir/ ../out/$APP"-"$VERSION"-"$ARCH".AppImage" | |
150 | } | |
151 | ||
152 | # Generate AppImage type 2 | |
153 | generate_type2_appimage() | |
154 | { | |
155 | # Get the ID of the last successful build on Travis CI | |
156 | # ID=$(wget -q https://api.travis-ci.org/repos/probonopd/appimagetool/builds -O - | head -n 1 | sed -e 's|}|\n|g' | grep '"result":0' | head -n 1 | sed -e 's|,|\n|g' | grep '"id"' | cut -d ":" -f 2) | |
157 | # Get the transfer.sh URL from the logfile of the last successful build on Travis CI | |
158 | # Only Travis knows why build ID and job ID don't match and why the above doesn't give both... | |
159 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+1))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') | |
160 | # if [ -z "$URL" ] ; then | |
161 | # URL=$(wget -q "https://s3.amazonaws.com/archive.travis-ci.org/jobs/$((ID+2))/log.txt" -O - | grep "https://transfer.sh/.*/appimagetool" | tail -n 1 | sed -e 's|\r||g') | |
162 | # fi | |
163 | URL="https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" | |
164 | wget -c "$URL" -O appimagetool | |
165 | chmod a+x ./appimagetool | |
166 | set +x | |
167 | if ( [ ! -z "$KEY" ] ) && ( ! -z "$TRAVIS" ) ; then | |
168 | wget https://github.com/probonopd/AppImageKit/files/584665/data.zip -O data.tar.gz.gpg | |
169 | ( set +x ; echo $KEY | gpg2 --batch --passphrase-fd 0 --no-tty --skip-verify --output data.tar.gz --decrypt data.tar.gz.gpg ) | |
170 | tar xf data.tar.gz | |
171 | sudo chown -R $USER .gnu* | |
172 | mv $HOME/.gnu* $HOME/.gnu_old ; mv .gnu* $HOME/ | |
173 | VERSION=$VERSION ./appimagetool -n -s --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ | |
174 | else | |
175 | VERSION=$VERSION ./appimagetool -n --bintray-user $BINTRAY_USER --bintray-repo $BINTRAY_REPO -v ./$APP.AppDir/ | |
176 | fi | |
177 | set -x | |
178 | mkdir -p ../out/ || true | |
179 | mv *.AppImage* ../out/ | |
180 | } | |
181 | ||
182 | # Generate status file for use by apt-get; assuming that the recipe uses no newer | |
183 | # ingredients than what would require more recent dependencies than what we assume | |
184 | # to be part of the base system | |
185 | generate_status() | |
186 | { | |
187 | mkdir -p ./tmp/archives/ | |
188 | mkdir -p ./tmp/lists/partial | |
189 | touch tmp/pkgcache.bin tmp/srcpkgcache.bin | |
190 | wget -q -c "https://github.com/probonopd/AppImages/raw/master/excludedeblist" | |
191 | rm status 2>/dev/null || true | |
192 | for PACKAGE in $(cat excludedeblist | cut -d "#" -f 1) ; do | |
193 | printf "Package: $PACKAGE\nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n" >> status | |
194 | done | |
195 | } | |
196 | ||
197 | # Find the desktop file and copy it to the AppDir | |
198 | get_desktop() | |
199 | { | |
200 | find usr/share/applications -iname "*${LOWERAPP}.desktop" -exec cp {} . \; || true | |
201 | } | |
202 | ||
203 | # Find the icon file and copy it to the AppDir | |
204 | get_icon() | |
205 | { | |
206 | find ./usr/share/pixmaps/$LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
207 | find ./usr/share/icons -path *64* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
208 | find ./usr/share/icons -path *128* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
209 | find ./usr/share/icons -path *512* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
210 | find ./usr/share/icons -path *256* -name $LOWERAPP.png -exec cp {} . \; 2>/dev/null || true | |
211 | ls -lh $LOWERAPP.png || true | |
212 | } | |
213 | ||
214 | # Find out the version | |
215 | get_version() | |
216 | { | |
217 | THEDEB=$(find ../*.deb -name $LOWERAPP"_*" | head -n 1) | |
218 | if [ -z "$THEDEB" ] ; then | |
219 | echo "Version could not be determined from the .deb; you need to determine it manually" | |
220 | fi | |
221 | VER1=$(echo $THEDEB | cut -d "~" -f 1 | cut -d "_" -f 2 | cut -d "-" -f 1 | sed -e 's|1%3a||g' | sed -e 's|+dfsg||g' ) | |
222 | GLIBC_NEEDED=$(glibc_needed) | |
223 | VERSION=$VER1.glibc$GLIBC_NEEDED | |
224 | echo $VERSION | |
225 | } | |
226 | ||
227 | # transfer.sh | |
228 | transfer() { if [ $# -eq 0 ]; then echo "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md"; return 1; fi | |
229 | tmpfile=$( mktemp -t transferXXX ); if tty -s; then basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g'); curl --progress-bar --upload-file "$1" "https://transfer.sh/$basefile" >> $tmpfile; else curl --progress-bar --upload-file "-" "https://transfer.sh/$1" >> $tmpfile ; fi; cat $tmpfile; rm -f $tmpfile; } | |
230 | ||
231 | # Patch binary files; fill with padding if replacement is shorter than original | |
232 | # http://everydaywithlinux.blogspot.de/2012/11/patch-strings-in-binary-files-with-sed.html | |
233 | # Example: patch_strings_in_file foo "/usr/local/lib/foo" "/usr/lib/foo" | |
234 | function patch_strings_in_file() { | |
235 | local FILE="$1" | |
236 | local PATTERN="$2" | |
237 | local REPLACEMENT="$3" | |
238 | # Find all unique strings in FILE that contain the pattern | |
239 | STRINGS=$(strings ${FILE} | grep ${PATTERN} | sort -u -r) | |
240 | if [ "${STRINGS}" != "" ] ; then | |
241 | echo "File '${FILE}' contain strings with '${PATTERN}' in them:" | |
242 | for OLD_STRING in ${STRINGS} ; do | |
243 | # Create the new string with a simple bash-replacement | |
244 | NEW_STRING=${OLD_STRING//${PATTERN}/${REPLACEMENT}} | |
245 | # Create null terminated ASCII HEX representations of the strings | |
246 | OLD_STRING_HEX="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00" | |
247 | NEW_STRING_HEX="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00" | |
248 | if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then | |
249 | # Pad the replacement string with null terminations so the | |
250 | # length matches the original string | |
251 | while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do | |
252 | NEW_STRING_HEX="${NEW_STRING_HEX}00" | |
253 | done | |
254 | # Now, replace every occurrence of OLD_STRING with NEW_STRING | |
255 | echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... " | |
256 | hexdump -ve '1/1 "%.2X"' ${FILE} | \ | |
257 | sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \ | |
258 | xxd -r -p > ${FILE}.tmp | |
259 | chmod --reference ${FILE} ${FILE}.tmp | |
260 | mv ${FILE}.tmp ${FILE} | |
261 | echo "Done!" | |
262 | else | |
263 | echo "New string '${NEW_STRING}' is longer than old" \ | |
264 | "string '${OLD_STRING}'. Skipping." | |
265 | fi | |
266 | done | |
267 | fi | |
268 | } |