/var/lib/sorcery/modules/libgrimoire
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ##
4 ## @Libgrimoire
5 ##
6 ## @Synopsis Set of functions containing the spell writing API.
7 ##
8 ##
9 ## These functions can be used in the PRE_BUILD, BUILD, POST_BUILD
10 ## and POST_INSTALL sections of spells.
11 ##
12 ## @Copyright
13 ## Original version Copyright 2001 by Kyle Sallee
14 ## Additions/Corrections Copyright 2002 by the Source Mage Team
15 ##
16 #---------------------------------------------------------------------
17
18 #---------------------------------------------------------------------
19 ## @Type API
20 ## @param directory name
21 ## @param [size]
22 ## Creates a tmpfs filesystem. By default, the size is 1GB.
23 ## The caller may optionally supply a size argument.
24 ## <pre>
25 ## Example1: Create a 2GB mount at $SOURCE_DIRECTORY
26 ##
27 ## mk_source_dir $SOURCE_DIRECTORY 2g
28 ##
29 ## Example2: Create a mount at /tmp/newdir, defaults to 2GB size
30 ##
31 ## mk_source_dir /tmp/newdir
32 ## </pre>
33 #---------------------------------------------------------------------
34 function real_mk_source_dir() {
35
36 debug "libgrimoire" "Running mk_source_dir() on ${1:-SOURCE_DIRECTORY} with size ${2:-2g}"
37
38 local NEW_DIR=$1
39 local NEW_DIR=${NEW_DIR:=$SOURCE_DIRECTORY}
40
41 local SIZE=$2
42 local SIZE=${SIZE:=2g}
43
44 if [ -n "$NEW_DIR" ]; then
45
46 rm_source_dir $NEW_DIR
47 mkdir -p $NEW_DIR &&
48 if [[ $TMPFS == on ]]; then
49 mount -o size=$SIZE,nr_inodes=1m -t tmpfs tmpfs $NEW_DIR
50 fi
51 fi
52
53 }
54
55
56 #---------------------------------------------------------------------
57 ## @param [directory to remove]
58 ## @Globals SOURCE_DIRECTORY
59 ## Removes the given directory or SOURCE_DIRECTORY if no argument is
60 ## given.
61 ##
62 #---------------------------------------------------------------------
63 function real_rm_source_dir() {
64
65 local dead_dir="${1:-$SOURCE_DIRECTORY}"
66 dead_dir=$(readlink -f "$dead_dir")
67
68 debug "libgrimoire" "Running rm_source_dir() on $dead_dir"
69
70 if [[ -n $dead_dir ]] && [[ -d $dead_dir ]]; then
71 if [[ $dead_dir == $SOURCE_DIRECTORY ]] &&
72 [[ ${SOURCE_DIRECTORY#$BUILD_DIRECTORY} == $SOURCE_DIRECTORY ]]; then
73 error_message "The source directory ($SOURCE_DIRECTORY) is not under the build"
74 error_message "directory ($BUILD_DIRECTORY)! Refusing deletion for safety reasons!"
75 error_message "Please report this bug to http://bugs.sourcemage.org"
76 return 1
77 fi
78
79 pushd $BUILD_DIRECTORY 2>&1 > /dev/null
80
81 # make sure nothing recursive is mounted under deaddir
82 local mount on mountloc rest
83 mount |
84 while read mount on mountloc rest
85 do
86 if echo $mountloc | grep -q "^$dead_dir"
87 then
88 debug "libgrimoire" "Unmounting $mount on $mountloc"
89 umount -l $mountloc 2> /dev/null
90 fi
91 done
92
93 # We don't really want to use "rm -rf", but if not using tmpfs,
94 # we have to. So we move the old dir to a known place before
95 # running rm. This prevents accidental damage that could be
96 # caused by
97 # a) $dead_dir being an empty string
98 # b) $dead_dir being set to "/" (or anything above /usr/src)
99 # c) $dead_dir containing metacharacters (like newline)
100 mv "$dead_dir" "$BUILD_DIRECTORY/deaddir" &&
101 rm -rf "$BUILD_DIRECTORY/deaddir" 2> /dev/null
102
103 popd 2>&1 > /dev/null
104 true
105
106 fi
107
108 }
109
110
111 #---------------------------------------------------------------------
112 ##
113 ## Override calls to the make program. Used to add custom arguments and
114 ## handle failures when using multiple jobs.
115 ##
116 #---------------------------------------------------------------------
117 function make() {
118
119 local JOBS=""
120
121 local make_njobs=${MAKE_NJOBS:-1}
122 local jobs_per_host=${JOBS_PER_HOST:-0}
123 local tmp num_hosts=0
124 for tmp in $DISTCC_HOSTS; do let num_hosts+=1; done
125 local JOBS
126
127 # if the parent didnt define this, define it here
128 if [[ ! "$REAL_MAKE" ]] ; then
129 local REAL_MAKE
130 find_make REAL_MAKE || return $?
131 fi
132
133
134 if [[ "$USE_DISTCC" == on ]] ; then
135 let JOBS=$(($make_njobs+$jobs_per_host*$num_hosts))
136 else
137 let JOBS=$make_njobs
138 fi
139
140 if [[ $JOBS == 0 ]]; then
141 # Zero jobs has the effect of unlimiting the number of make processes
142 JOBS=""
143 else
144 # Check there is a reasonable value.
145 [ $JOBS -lt 0 ] ||
146 echo $JOBS|grep -q '[0-9]+' &&
147 JOBS="1" # Use default of one when MAKE_NJOBS is nonsense.
148 fi
149
150 debug "libgrimoire" "make: running with $JOBS jobs"
151 $REAL_MAKE -j $JOBS -S "$@"
152
153 # Cache the result
154 local STATUS=$?
155
156 if [[ $STATUS -ne 0 ]] && [[ "$JOBS" != 1 ]] ; then
157 query "Running make with $JOBS jobs failed. Attempt to run with a single job?" y >&3 &&
158 # Try again
159 $REAL_MAKE -j1 -S "$@"
160 STATUS=$?
161 fi
162
163 # Return the exit status
164 return $STATUS
165
166 }
167
168 #---------------------------------------------------------------------
169 ## Install files in a spells "desktop" subdirectory for .desktop
170 ## @param Spell
171 ## @Stdout file name
172 #---------------------------------------------------------------------
173 function install_desktop_files() {
174 debug "libgrimoire" "Running install_desktop_files() on $SPELL"
175 local each file
176 local target_dir
177 local desktop_dir="$SCRIPT_DIRECTORY/desktop"
178 test -d $desktop_dir || return 0
179
180 if [[ $STAGED_INSTALL == off ]]; then
181 target_dir="$INSTALL_ROOT/usr/share/applications"
182 else
183 target_dir="$STAGE_DIRECTORY/TRANSL/usr/share/applications"
184 fi
185
186 mkdir -p $target_dir
187 for each in $(find $desktop_dir -maxdepth 1 -type f); do
188 smgl_basename "$each" file
189 if ! test -f "$target_dir/$file" ; then
190 debug "libgrimoire" "Installing $file in $target_dir as a desktop file"
191 install -g root -o root $each $target_dir
192 fi
193 done
194 }
195
196
197 #---------------------------------------------------------------------
198 ## @Type API
199 ## @param spell
200 ##
201 ## Returns the current version of the given spell
202 ##
203 #---------------------------------------------------------------------
204 function real_installed_version() {
205 spell_ok $1 || return
206 private_installed_version "$@"
207 }
208
209 #---------------------------------------------------------------------
210 ## @Type API
211 ## @param spell
212 ## Returns the current version of the given spell
213 ## Doesnt do sanity check for spell_ok, used internally for speed.
214 ## Behavior is undefined is spell is not installed.
215 ##
216 #---------------------------------------------------------------------
217 function private_installed_version() {
218 awk -F: -v spell="$1" '{ if(spell == $1) {print $4; exit}}' $SPELL_STATUS 2>/dev/null
219 }
220
221 #---------------------------------------------------------------------
222 ## @param spell
223 ## @param default answer to dispel query
224 ## @Type API
225 ## If the default answer is anything other than 'y' then 'n' is assumed.
226 ## returns the given spellname if it is installed
227 ##
228 #---------------------------------------------------------------------
229 function real_conflicts() {
230 debug "libgrimoire" "Running conflicts() on $1. Default query answer $2."
231
232 if spell_ok $1; then
233 if [[ $2 == y ]]; then
234 echo "$1:y"
235 else
236 echo "$1:n"
237 fi
238 fi
239 }
240
241 #---------------------------------------------------------------------
242 ## @Stdout Warning messages.
243 ## Provides a neatly formatted rejection dialog for the
244 ## various rejected spells that might require user warnings.
245 ## See ask_continue_with_rejected for second part of this function.
246 ##
247 #---------------------------------------------------------------------
248 function warn_rejected()
249 {
250 message "${MESSAGE_COLOR}This spell is considered${PROBLEM_COLOR}" \
251 "rejected${DEFAULT_COLOR}${MESSAGE_COLOR} because of the" \
252 "following reason:\n"
253 message "${PROBLEM_COLOR}$REJECT${DEFAULT_COLOR}${MESSAGE_COLOR}.\n"
254 message "Please view the software website for more information:\n"
255 message "${DEFAULT_COLOR}$WEB_SITE${MESSAGE_COLOR}\n"
256 message "You may continue casting the spell and it will still be tracked" \
257 "by Sorcery.\nHowever, the software installation process may have" \
258 "questions that need to be\nanswered and/or licensing agreements" \
259 "that must be agreed to.${DEFAULT_COLOR}\n"
260 }
261
262
263 #---------------------------------------------------------------------
264 ## @Stdout Question
265 ## @Stdin Answer ;-)
266 ## Part two of the warn_rejected funtion, ask if user wants to continue
267 ## anyway. (defaults to NO), unless running in UNATTEND_SAFE mode.
268 ##
269 #---------------------------------------------------------------------
270 function ask_continue_with_rejected()
271 {
272 if spell_installed "$SPELL" && [ -e $SCRIPT_DIRECTORY/UNATTEND_SAFE ]; then
273 message "${SPELL_COLOR}$SPELL${DEFAULT_COLOR}${MESSAGE_COLOR} is" \
274 "installed, and has been determined" \
275 "to be ${FILE_COLOR}safe\nfor unattended" \
276 "update${DEFAULT_COLOR}${MESSAGE_COLOR}, so the prompt will" \
277 "be skipped.${DEFAULT_COLOR}\n"
278 return
279 fi
280 message "\n${MESSAGE_COLOR}Allowing the next question to timeout will" \
281 "choose not to install this spell.\nThis means that rejected" \
282 "spells ${PROBLEM_COLOR}will not be installed or updated" \
283 "automatically.\n"
284 message "${DEFAULT_COLOR}${MESSAGE_COLOR}If you want a rejected spell to" \
285 "be installed or updated you must\nconfirm your decision now or" \
286 "cast the spell later.${DEFAULT_COLOR}\n"
287 if ! query "CONTINUE casting?" n; then
288 return 1
289 fi
290 message "\n${MESSAGE_COLOR}OK, here we go... you are on your" \
291 "own!${DEFAULT_COLOR}"
292 }
293
294
295 #---------------------------------------------------------------------
296 ## @License
297 ##
298 ## This software is free software; you can redistribute it and/or modify
299 ## it under the terms of the GNU General Public License as published by
300 ## the Free Software Foundation; either version 2 of the License, or
301 ## (at your option) any later version.
302 ##
303 ## This software is distributed in the hope that it will be useful,
304 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
305 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
306 ## GNU General Public License for more details.
307 ##
308 ## You should have received a copy of the GNU General Public License
309 ## along with this software; if not, write to the Free Software
310 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
311 ##
312 #---------------------------------------------------------------------