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