root/main/trunk/makepackage

Revision 2522, 76.5 kB (checked in by jhasse, 3 weeks ago)

Warning for creating <1.4 packages with x86_64 binaries in them and a minor fix for stub.4.template.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/bin/bash
2
3 # ------------------------------------------------------------
4 #       autopackage creator program
5 # ------------------------------------------------------------
6
7 ###
8 #
9 # This code is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation; either
12 # version 2.1 of the License, or (at your option) any later version.
13 #
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Lesser General Public License for more details.
18 #
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with this library; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 #
23 # Copyright 2002-2005 Mike Hearn (mike@plan99.net),
24 # Hongli Lai (hongli@plan99.net) and others.
25 #
26
27
28 # Some important variables:
29 # $metadata_dir
30 # $payload_dir
31 #       These variables refer to the metadata and payload directories
32 #       of the package that's currently being created.
33
34 # Output a sample specfile if --mkspec is given.
35 if [[ "$1" == "--mkspec" ]]; then
36         cat <<EOF
37 # -*-shell-script-*-
38
39 #
40 # This is an example specfile. Delete these comments when you're done.
41 #
42
43 [Meta]
44 RootName: @mysite.org/myproject:\$SOFTWAREVERSION
45 DisplayName: MyProject Strategy Game
46 ShortName: myproject
47 Maintainer: John Smith <smith@mysite.org>
48 Packager: John Smith <smith@mysite.org>
49 Summary: MyProject is an example
50 URL: http://www.mysite.org/
51 License: GNU General Public License, Version 2
52 SoftwareVersion: 1.0
53 # SoftwareVersion: @VERSION@
54 Repository: http://www.mysite.org/downloads/myproject.xml
55
56 # If you change the autopackage but not the software itself,
57 # increment this number.
58
59 # PackageVersion: 2
60
61 # This is the version of the autopackage runtime this package is
62 # written for. Increasing this number implies you have read the
63 # "Migrating to 1.X" document and understand the impact it will have
64 # on your package. Some APIs may change their behaviour and new
65 # features will be enabled depending on what this is set to.
66 AutopackageTarget: 1.4
67
68 # Only uncomment InterfaceVersion if your package exposes interfaces
69 # to other software, for instance if it includes DSOs or python/perl
70 # modules. See the developer guide for more info, or ask on
71 # autopackage-dev if you aren't sure about interface versioning.
72 #
73 # InterfaceVersion: 0.0
74
75 [BuildPrepare]
76 # For ./configure based systems this is a good default
77 prepareBuild --with-some-feature
78
79 [BuildUnprepare]
80 unprepareBuild
81
82 [Globals]
83 # Anything put here will be run during makeinstall and at
84 # install/uninstall time. Define useful variables here:
85
86 # export MY_VAR=1
87
88 [Imports]
89 # You may wish to delete some things first, eg libtool .la files or
90 # development files (headers)
91
92 # rm -r include
93 # rm libs/*.la
94
95 # This imports every file in $build_root
96 # (ie, that is installed by "make install")
97 echo '*' | import
98
99
100 [Prepare]
101 # Dependency checking
102
103 # You can use "require" and "recommend". They both try to find the
104 # given dependency, and install it if missing. But require will return
105 # 1 (causing failure) if it can't do that whereas recommend will
106 # simply show a notice at the end of the install.
107
108 # The second argument here identifies a skeleton file, which is
109 # a file that encapsulates a dependency check. The second number
110 # identifies the interface version you need. Use as many of these
111 # as you need.
112
113 require @whatever.you/need 1.0
114
115 # The user may have already installed the program from an RPM.
116 # Let's try and uninstall it first. We only need one call if 3rd party
117 # packages have split the program up into multiple packages.
118
119 removeOwningPackage \$PREFIX/bin/my-program
120
121 [Install]
122 # Put your installation script here. See the quickstart guide on
123 # the website for an API cheat-sheet
124 installExe bin/*
125
126 [Uninstall]
127 # Usually just the following line is enough to uninstall everything
128 uninstallFromLog
129 EOF
130         exit
131 fi
132
133
134 # setup XDG configuration variables scoped for autopackage
135 #
136 #   AUTOPACKAGE_CONFIG_HOME     User configuration directory
137 #   AUTOPACKAGE_CONFIG_DIRS     System configuration directories
138 #   AUTOPACKAGE_CONFIG_DIR      Determined system configuration directory for autopackage
139
140 if [ -z "$AUTOPACKAGE_CONFIG_HOME" ]; then
141     export AUTOPACKAGE_CONFIG_HOME
142     if [ -z "$XDG_CONFIG_HOME" ]; then
143         AUTOPACKAGE_CONFIG_HOME="$HOME/.config"
144     else
145         AUTOPACKAGE_CONFIG_HOME="$XDG_CONFIG_HOME"
146     fi
147 fi
148
149 if [ -z "$AUTOPACKAGE_CONFIG_DIRS" ]; then
150     export AUTOPACKAGE_CONFIG_DIRS
151     if [ -z "$XDG_CONFIG_DIRS" ]; then
152         AUTOPACKAGE_CONFIG_DIRS="/etc/xdg"
153     else
154         AUTOPACKAGE_CONFIG_DIRS="$XDG_CONFIG_DIRS"
155     fi
156 fi
157
158 if [ -z "$AUTOPACKAGE_CONFIG_DIR" ]; then
159     export AUTOPACKAGE_CONFIG_DIR
160     _AUTOPACKAGE_CONFIG_DIRS=$( echo "$AUTOPACKAGE_CONFIG_DIRS" | tr ':' ' ' )
161     for _CONFIGURATION_DIR in $_AUTOPACKAGE_CONFIG_DIRS; do
162         if [ -e "$_CONFIGURATION_DIR/autopackage/config" ]; then
163             AUTOPACKAGE_CONFIG_DIR="$_CONFIGURATION_DIR"
164             break
165         fi
166     done
167     unset _AUTOPACKAGE_CONFIG_DIRS
168 fi
169
170 # set defaults that might not be loaded from system configurations
171 export autopackage_deny_user=false
172
173 # load system configurations
174 [ -e /etc/autopackage/config ] && source /etc/autopackage/config;
175 [ -e "$AUTOPACKAGE_CONFIG_DIR/autopackage/config" ] && source "$AUTOPACKAGE_CONFIG_DIR/autopackage/config";
176
177 # load user configuration if allowed from system configuration
178 if ! $autopackage_deny_user; then
179     [ -e "$AUTOPACKAGE_CONFIG_HOME/autopackage/config" ] && source "$AUTOPACKAGE_CONFIG_HOME/autopackage/config";
180 fi
181
182 [ -e "`dirname \"$0\"`/etc/config-not-installed" ] && source "`dirname \"$0\"`/etc/config-not-installed"
183
184 _apspec_dir="`pwd`/autopackage"
185
186 if [[ "$autopackage_prefix" != "" ]]; then
187         pushd "$autopackage_share" >/dev/null
188         source "apkg-funclib"
189         popd >/dev/null
190 else
191         # link to autopackage functions and environment
192         # sideload by changing into dir to source files within that directory
193         pushd "$autopackage_share" >/dev/null
194         source "../etc/config"
195         source "apkg-funclib"
196         popd >/dev/null
197
198         # check and install SVN directory apbuild
199         _installApbuild -q
200 fi
201
202 myname=`basename "$0"`
203 mydir=`dirname "$0"`
204 mydir=`cd "$mydir"; pwd`
205 alias makepackage="$mydir/$myname"
206 unset myname
207 unset mydir
208
209 apkg_logfile="/dev/null"
210 apkg_filelist="/dev/null"
211
212 # initialize variables
213 _initializeAutopackage
214
215 checkConfigVersion || exit 1;
216
217 # error codes
218 ERROR_NO_STUB=1;
219 ERROR_NO_INSTALLER=2;
220 ERROR_NO_DOWNLOADER=3;
221 ERROR_MISSING_SKELETON=5;
222 ERROR_SKELETON_API_MISMATCH=6;
223
224 ###############################################################
225 ## start here
226
227 # check for command line arguments
228 while getopts ":hcms" Option
229 do
230         case $Option in
231                 c )
232                         export APKG_BUILD_SKIP_CONFIGURE=1
233                         ;;
234                 m )
235                         export APKG_BUILD_SKIP_MAKE=1
236                         ;;
237
238         s )
239             export APKG_NO_STRIP=1
240             ;;
241
242                 h | * ) # output help text and unknown cases
243                         echo
244                         out "autopackage installer builder
245 Usage from source directory root:
246     makepackage [--mkspec] | ['apspec-filename1' 'apspec-filename2' ... ]
247
248 If --mkspec is given, makepackage will print a sample specfile to standard
249 output. You can use this as a starting point for writing a new specfile.
250
251 If --mkspec is not given, makepackage will create a new .package based
252 on the given specfiles. If no specfile filename is declared then
253 spec filename autopackage/default.apspec will be used.
254
255 The script will create a software package that will
256 be written to the file specified in the spec file.
257
258 Options:
259    -c     Do not run './configure' when building this package
260           (only useful if you use prepareBuild)
261    -m     Do not run 'make' when building this package
262           (only useful if you use prepareBuild)
263    -s     Do not strip ELF binaries
264           (useful if you want to send a debug build to somebody)
265    -h     Show this help screen"
266                         echo
267                         exit 0;;
268         esac
269 done
270 shift $(($OPTIND - 1))
271
272 # This function uses xsltproc to transform XDG spec mime-type files
273 # into the KDE 3.x equivalents. Symlinks are created so that installMime
274 # can automatically install both the XDG and KDE mime-types.
275 # XML files must be located located in $build_root/share/mime/packages, otherwise
276 # broken symlinks will be constructed (links are made relative to share/mime/packages).
277 # NOTE: Private function, do not use in specfiles.
278
279 function generateLegacyMime() {
280     outn "Converting XDG MIME type definitions to KDE 3.x equivalents ... "
281     if locateCommand xsltproc; then
282         # deal with KDE mime-types
283
284         mkdir -p "$payload_dir/share/mimelnk"
285         pushd "$payload_dir/share/mimelnk" > /dev/null
286         for mimefile in $@; do
287             if ! grep -q "http://www.freedesktop.org/standards/shared-mime-info" "$mimefile"; then
288                 red; outn "WARNING: "; normal; out "The FreeDesktop.org MIME Type file `basename "$mimefile"` does not appear to have a namespace declaration. KDE 3.x MIME Type files will not be generated."
289             fi
290
291             local i=0 # counts number of .desktop files created from a single XML file (for symlinks--hello.xml.1)
292             for mimetype in $( $lc_location $autopackage_share/apkg-mimetype.xsl $mimefile ); do
293                 let i+=1
294                 # this command is run from share/mimelnk (so xsltproc files land in the right placage)
295                 # which is why the symlink is constructed from ../../share/mime/packages to share/mimelnk/
296                 ln -fs "../../../share/mimelnk/$mimetype.desktop" ../../share/mime/packages/`basename $mimefile.$i`
297             done
298         done
299         popd > /dev/null
300     else
301         err "You need xsltproc installed to process mime-types."
302     fi
303     green; out "done"; normal
304 }
305
306 function safeRemove()
307 {
308     test -z "$1" -o -z "${TMP}" && return
309     # Only remove paths in ${TMP}
310     if [[ "$1" == ${TMP}/* ]]; then
311         rm -rf "$1"
312     fi
313 }
314
315 function cleanUp()
316 {
317     safeRemove "$payload_dir"
318     safeRemove "$metadata_dir"
319     safeRemove "$current_directory"
320     safeRemove "$_virtual_build_root"
321     safeRemove "$__apkg_errors_file"
322     unset payload_dir
323     unset metadata_dir
324     unset build_root
325     unset __apkg_errors_file
326     # all temporary files are prefixed with apkg-
327     rm -fr "${TMP}"/apkg-*
328     return 0
329 }
330
331 trap cleanUp EXIT
332
333 # Process a specfile
334 function process()
335 {
336         # **********************************************************
337         #  Process for building a .package file
338         #
339         #  1. Setup environment variables and perform sanity checks
340         #
341         #  2. Parse package metadata from Meta section of specfile
342         #
343         #  3. Load template files and substitute values
344         #
345         #  4. Generate build_root and run BuildPrepare
346         #
347         #  5. Import files into package
348         #
349         #  6. Create script files in meta directory
350         #
351         #  7. Start creating the package file
352         #
353         #  8. Generate package output files depending on type
354         # **********************************************************
355
356
357         # **********************************************************
358         #  1. Setup environment variables and sanity checks
359         # **********************************************************
360         local specfile="$1"
361         # The working directory from which makepackage is invoked;
362         # usually the directory containing the source code.
363         export source_dir
364         # The main data payload directory
365         payload_dir="${TMP}/apkg-payload-dir$$-$RANDOM"
366         # The metadata payload directory
367         export metadata_dir="${TMP}/apkg-meta$RANDOM$$"
368
369         # The compiled files get copied to this dir. The extraction script
370         # will copy files from this dir to $payload_dir
371         export build_root="."
372
373         # The apspec directory to search for skeleton files which is used in
374         # _locateSkeleton function from apkg-dep.
375         local __apkg_errors_file
376         local oIFS
377         local language
378
379         local f
380         local l
381
382         # Is this specfile generated from a .apspec.in template? If so,
383         # check if .apspec.in is newer than .apspec, and if yes regen
384         if [[ -e config.status && -e "${specfile}.in" ]]; then
385             ./config.status --file="$specfile"
386             local exitCode=$?
387
388             if [ $exitCode != 0 ]; then
389                 return $exitCode
390             fi
391         fi
392
393         if [ ! -e "$specfile" ]; then
394                 red; outn "FAIL: "; normal;
395                 out "$specfile could not be found"
396                 return 1
397         fi
398
399         if file "$specfile" | grep -q CRLF; then
400                 red; outn "ERROR: "; normal; out "Specfile %s contains Windows line terminators (CRLF) and is therefore not compatible with makepackage." "$specfile"
401                 if yesNo "Should makepackage fix this for you? (Y/n)"; then
402                         sed 's/\r$//' -i "$specfile"
403                 else
404                         return 1
405                 fi
406         fi
407
408         # Ensure we have an absolute path
409         source_dir=`pwd`;
410         if [[ ${specfile:0:1} != "/" ]]; then
411             # Get absolute filename of specfile if it isn't an absolute filename already
412             specfile="$source_dir/$specfile"
413         fi
414
415         mkdir -p "$payload_dir"
416         chmod 700 "$payload_dir"
417
418         # Check the specfile exists
419         if [ ! -e "$specfile" ]; then
420                 red; out "$specfile could not be found"; normal;
421                 return 1
422         fi
423
424
425         drawHeaderBlue "Building installer for %s" "$specfile"
426
427         # **********************************************************
428         #  2. Parse package metadata from Meta section of specfile
429         # **********************************************************
430
431         # **********************************************************
432         #  2.1 Load specfile meta data
433         # **********************************************************
434         local meta meta_localized meta_matched
435         meta=`getSection "$specfile" Meta`
436         meta=`stripComments "$meta"`
437         # **********************************************************
438         #  2.2 Convert Meta section keys to variables
439         # **********************************************************
440         trace processing Meta section keys to variables
441         trace "$meta"
442         if [[ "$meta" != "" ]]; then
443                 function subup()
444                 {
445                         # grab non-localized keys to start
446                         if (( `echo "$meta_localized" | grep -i "^$1:" | wc -l` > 1 )); then
447                                 err "Key $1 is duplicated, ignoring all but first"
448                         fi
449
450                         local line=`echo "$meta_localized" | grep -i "^$1:" | head -n 1`
451                         local start=`echo "$line" | awk 'BEGIN { FS=": " } { print $1 }' | sed 's/@/\_\_at\_\_/g'`
452                         local value=`echo "$line" | awk 'BEGIN { FS=": " } { print $2 }'`
453                         # continue if the specKey is found in the Meta section keys
454                         if [[ "$start" != "" ]]; then
455                                 # translate key to CAPITALS
456                                 local up=$( echo "$start" | tr 'a-z' 'A-Z' )
457                                 # write CAPITAL case key new meta variable which only allows specified specKeys
458                                 trace substituting meta key $start to be $up
459                                 meta_matched=$( echo "$meta_matched"; echo "${up}=\"${value}" );
460                                 # process localized keys
461                                 oIFS="$IFS"
462                                 IFS=$'\n'
463                                 for line in `echo "$meta_localized" | grep -i "^${start}\["`; do
464                                         line=$( echo "$line" | sed "s/^${start}\[/${up}_/g" );
465                                         meta_matched=$( echo "$meta_matched"; echo "${line}" );
466                                 done
467                                 IFS="$oIFS"
468                         fi
469                 }
470
471                 # copy meta data to new variable
472                 meta_localized=`echo "$meta"`
473
474                 # converting Meta section keys to environment variables changes
475                 # the meta data between the listed formats and subup translates
476                 # the specKeys to be CAPITALS.
477                 # DisplayName: <data>           --->    DISPLAYNAME="<data>"
478                 # DisplayName[fr]: <data>       --->    DISPLAYNAME_fr="<data>"
479                 # Summary: <data>               --->    SUMMARY="<data>"
480                 # Summary[fr]: <data>           --->    SUMMARY_fr="<data>"
481                 # Summary[fr@Latn]: <data>      ---->   SUMMARY_fr__at__Latn="<data>"
482                 #
483                 # allow ':' to be used in Meta data, need to focus on the first instance of ':'
484                 # first instance can be determined on localized keys because of the ']: ' so substitute in '='
485                 # and non-localized keys are converted to variables in subup function
486                 meta_localized=`echo "$meta_localized" | sed 's/\]: /\=\"/g'`
487                 meta_localized=`echo "$meta_localized" | sed 's/\(.\)$/\1"/g'`
488
489                 for state in $specKeys; do
490                         subup "${state}"
491                 done
492
493                 unset subup meta_localized
494         fi
495
496         # Unset specfile meta keys
497         _resetKeys
498
499         # Evaluate Meta section key
500         trace evaluating Meta section key variables
501         trace "$meta_matched"
502         # evaluate to define values
503         eval "$meta_matched" >/dev/null
504         # allow any values to be substituted
505         eval "$meta_matched" >/dev/null
506
507         # **********************************************************
508         #  2.3 Meta Sanity checks
509         # **********************************************************
510         if [[ "$DISPLAYNAME" == "" && "$PACKAGEDESKTOP" == "" ]]; then red; outn "FAIL: "; normal; out "No DisplayName key found in the [Meta] section. You need one"; cleanUp; return 1; fi
511         if [[ "$SHORTNAME" == "" ]]; then red; outn "FAIL: "; normal; out "No ShortName key found in the [Meta] section."; cleanUp; return 1; fi
512         if [[ "$ROOTNAME" == "" ]]; then red; outn "FAIL: "; normal; out "You forgot the RootName key in the [Meta] section. That's pretty important you know "; cleanUp; return 1; fi
513         if [[ "$SOFTWAREVERSION" == "" ]]; then red; outn "FAIL: "; normal; out "No SoftwareVersion key found in the [Meta] section, please add one"; cleanUp; return 1; fi
514         if [[ "$PACKAGEVERSION" != "" ]] && ! isInteger "$PACKAGEVERSION"; then red; outn "FAIL: "; normal; out "A valid PackageVersion key was not found in the [Meta] section. PackageVersion is an integer greater than 0."; cleanUp; return 1; fi
515         if [[ "$UPDATEFOR" != "" && "$AUTOPACKAGETARGET" < "1.4" ]]; then red; outn "FAIL "; normal; out "You need to set AutopackageTarget to at least 1.4 to use UpdateFor."; cleanUp; return 1; fi
516
517         trace ROOTNAME=$ROOTNAME
518         trace SHORTNAME=$SHORTNAME
519         trace SOFTWAREVERSION=$SOFTWAREVERSION
520         trace INTERFACEVERSION=$INTERFACEVERSION
521         trace DISPLAYNAME=$DISPLAYNAME
522         trace AUTOPACKAGETARGET=$AUTOPACKAGETARGET
523
524         # follow-up error checks on ROOTNAME
525         unset _rootname_match
526         # should be a leading @
527         if [ -z "$_rootname_match" ]; then
528                 _rootname_match=$( expr index "$ROOTNAME" "@" )
529                 if ! (( _rootname_match == 1 )); then
530                         _rootname_match="no leading @"
531                 else
532                         unset _rootname_match
533                 fi
534         fi
535         # should be no spaces
536         if [ -z "$_rootname_match" ]; then
537                 _rootname_match=$( expr index "$ROOTNAME" " " )
538                 if (( _rootname_match > 0 )); then
539                         _rootname_match="spaces"
540                 else
541                         unset _rootname_match
542                 fi
543         fi
544         # catch protocols
545         if [ -z "$_rootname_match" ]; then
546                 _rootname_match=$( echo "$ROOTNAME" | grep 'http://' )
547                 [ -n "$_rootname_match" ] && _rootname_match="http://"
548         fi
549         if [ -z "$_rootname_match" ]; then
550                 _rootname_match=$( echo "$ROOTNAME" | grep 'https://' )
551                 [ -n "$_rootname_match" ] && _rootname_match="https://"
552         fi
553         if [ -z "$_rootname_match" ]; then
554                 _rootname_match=$( echo "$ROOTNAME" | grep 'ftp://' )
555                 [ -n "$_rootname_match" ] && _rootname_match="ftp://"
556         fi
557         # should be at least one forward slash
558         if [ -z "$_rootname_match" ]; then
559                 _rootname_match=$( expr index "$ROOTNAME" "/" )
560                 if (( _rootname_match < 1 )); then
561                         _rootname_match="no secondary description"
562                 else
563                         unset _rootname_match
564                 fi
565         fi
566         # should be at least one colon
567         if [ -z "$_rootname_match" ]; then
568                 _rootname_match=$( expr index "$ROOTNAME" ":" )
569                 if (( _rootname_match < 1 )); then
570                         _rootname_match="no software version"
571                 else
572                         unset _rootname_match
573                 fi
574         fi
575         # send error if match exists from any of the previous tests
576         if [ -n "$_rootname_match" ]; then
577                 red; outn "ERROR: "; normal; out "Package RootName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for RootName guidelines." "$ROOTNAME" "$_rootname_match"
578                 return 1
579         fi
580
581         # follow-up warning checks on ROOTNAME
582         # should not have server name be 'www'
583         if [ -z "$_rootname_match" ]; then
584                 _rootname_match=$( echo "$ROOTNAME" | grep "@www" | wc -l )
585                 if (( _rootname_match > 0 )); then
586                         _rootname_match="www is not needed"
587                 else
588                         unset _rootname_match
589                 fi
590         fi
591         if [ -z "$_rootname_match" ]; then
592                 _rootname_match=$( versionFromRootName "$ROOTNAME" )
593                 if [[ "$_rootname_match" != "$SOFTWAREVERSION" ]]; then
594                         _rootname_match="root name version does not match software version"
595                 else
596                         unset _rootname_match
597                 fi
598         fi
599         # send warning if match exists from any of the previous tests
600         if [ -n "$_rootname_match" ]; then
601                 red; outn "WARNING: "; normal; out "Package RootName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for RootName guidelines." "$ROOTNAME" "$_rootname_match"
602         fi
603
604         # follow-up checks on SHORTNAME
605         unset _shortname_match
606         # should be no spaces
607         if [ -z "$_shortname_match" ]; then
608                 _shortname_match=$( expr index "$SHORTNAME" " " )
609                 if (( _shortname_match > 0 )); then
610                         _shortname_match="spaces"
611                 else
612                         unset _shortname_match
613                 fi
614         fi
615         # send error if match exists from any of the previous tests
616         if [ -n "$_shortname_match" ]; then
617                 red; outn "ERROR: "; normal; out "Package ShortName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for ShortName guidelines." "$SHORTNAME" "$_shortname_match"
618                 return 1
619         fi
620
621
622         # **********************************************************
623         #  2.4 Set Meta Defaults
624         # **********************************************************
625
626         # determine autopackage target api and normalize
627         local apkgtarget_major=`getMajor "$AUTOPACKAGETARGET"`
628         local apkgtarget_minor=`getMinor "$AUTOPACKAGETARGET"`
629         if [ `expr index "$apkgtarget_major" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ]; then
630                 apkgtarget_major="1"
631                 red; outn "WARNING: "; normal;
632                 out "No AutopackageTarget found in the specfile, default to '$apkgtarget_major'."
633         fi
634         if [ `expr index "$apkgtarget_minor" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ] || [[ "$apkgtarget_minor" == "" ]]; then
635                 apkgtarget_minor="0"
636         fi
637         if [[ "$apkgtarget_major" != "" ]]; then
638                 AUTOPACKAGETARGET="$apkgtarget_major.$apkgtarget_minor"
639         else
640                 AUTOPACKAGETARGET="1.2"
641                 red; outn "WARNING: "; normal;
642                 out "No AutopackageTarget found in the specfile, default to '$AUTOPACKAGETARGET'."
643         fi
644         trace setting api AUTOPACKAGETARGET=$AUTOPACKAGETARGET
645
646         COMPRESSION=`echo "$COMPRESSION" | tr [:upper:] [:lower:]`
647         if [[ "$COMPRESSION" != "" ]] &&
648            [[ "$COMPRESSION" != "bzip2" ]] &&
649            [[ "$COMPRESSION" != "lzma" ]]; then
650                 err "unknown compression method $COMPRESSION, selecting default"
651                 COMPRESSION=""
652         fi
653
654         if [[ "$COMPRESSION" == "" ]]; then
655                 if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
656                         COMPRESSION="bzip2"
657                 else
658                         COMPRESSION="lzma"
659                 fi
660         fi
661
662         if [[ "$AUTOPACKAGETARGET" == "1.0" ]] && [[ "$COMPRESSION" == "lzma" ]]; then
663                 err "LZMA compression is not available when targetting the 1.0 runtime, using bzip2."
664                 COMPRESSION="bzip2"
665         fi
666
667         if [[ "$COMPRESSION" == "lzma" ]] && ! locateCommand autopackage-lzma; then
668                 red; outn "WARNING: "; normal; out "Command 'autopackage-lzma' not found. bzip2 compression will be used instead."
669                 COMPRESSION="bzip2"
670         fi
671
672         if [[ -n $CPUARCHITECTURE ]] && [[ "$AUTOPACKAGETARGET" == "1.4" ]]; then
673                 red; outn "WARNING: "; normal; out "CPUArchitecture is deprecated. Use CPUArchitectures instead."
674         fi
675
676         # determine interface version and normalize
677         local interfaceversion_major=`getMajor "$INTERFACEVERSION"`
678         local interfaceversion_minor=`getMinor "$INTERFACEVERSION"`
679         if [[ -z "$INTERFACEVERSION" ]]; then
680                 trace defaulting INTERFACEVERSION=0.0
681                 INTERFACEVERSION="0.0"
682         elif [[ "$interfaceversion_minor" == "" ]]; then
683                 trace normalizing INTERFACEVERSION=$interfaceversion_major.0
684                 INTERFACEVERSION="$interfaceversion_major.0"
685         fi
686
687         if (( PACKAGEVERSION < 1 )); then
688                 PACKAGEVERSION="1"
689         fi
690
691         ROOTINSTALLONLY=`echo "$ROOTINSTALLONLY" | tr [:upper:] [:lower:]`
692         if [[ "$ROOTINSTALLONLY" == "yes" ]]; then
693                 ROOTINSTALLONLY="Yes"
694         elif [[ "$ROOTINSTALLONLY" == "no" ]]; then
695                 ROOTINSTALLONLY="No"
696         else
697                 trace defaulting ROOTINSTALLONLY="No"
698                 ROOTINSTALLONLY="No"
699         fi
700
701         PACKAGEREPORTING=`echo "$PACKAGEREPORTING" | tr [:upper:] [:lower:]`
702         if [[ "$PACKAGEREPORTING" == "yes" ]]; then
703                 PACKAGEREPORTING="Yes"
704         elif [[ "$PACKAGEREPORTING" == "no" ]]; then
705                 PACKAGEREPORTING="No"
706         else
707                 trace defaulting PACKAGEREPORTING="Yes"
708                 PACKAGEREPORTING="Yes"
709         fi
710
711         if [ -z "$REPOSITORYFILENAME" ]; then
712                 trace defaulting REPOSITORYFILENAME="$SHORTNAME.xml"
713                 REPOSITORYFILENAME="$SHORTNAME.xml"
714         fi
715
716         # gather repository value from skeleton file if a skeleton file exists
717         # always use skeleton repository value and warn if meta data also has a value set
718         # save repository to environment file if meta data is used
719         # set repository directory based on determined repository value
720         local m_skelfile=`_locateSkeleton "$ROOTNAME"`
721         if [ -n "$m_skelfile" ]; then
722                 m_repository=`getSectionKey "$m_skelfile" "Meta" "Repository"`
723         fi
724         local repository_dir=""
725         if [ -n "$m_repository" ] && [ -n "$REPOSITORY" ]; then
726                 if [[ "$m_repository" != "$REPOSITORY" ]]; then
727                         red; outn "WARNING: "; normal; out "Repository value from skeleton file '$m_skelfile' is being used instead of package meta data '$REPOSITORY'."
728                 fi
729                 # skeleton value is going to be used so clear meta data value
730                 REPOSITORY=""
731                 repository_dir=`dirname "$m_repository"`
732                 trace using skeleton repository value $m_repository instead of metadata value
733         elif  [ -n "$m_repository" ]; then
734                 repository_dir=`dirname "$m_repository"`
735                 trace using skeleton repository value $m_repository
736         elif  [ -n "$REPOSITORY" ]; then
737                 repository_dir=`dirname "$REPOSITORY"`
738                 trace using meta data repository value $REPOSITORY
739         fi
740         trace REPOSITORY=$REPOSITORY
741
742         EULADISPLAY=`echo "$EULADISPLAY" | tr [:upper:] [:lower:]`
743         if [[ "$EULADISPLAY" == "installation" ]]; then
744             EULADISPLAY="Installation"
745 #       elif [[ "$EULADISPLAY" == "execution" ]]; then
746 #           EULADISPLAY="Execution"
747 #       elif [[ "$EULADISPLAY" == "both" ]]; then
748 #           EULADISPLAY="Both"
749 #       elif [[ "$EULADISPLAY" == "none" ]]; then
750 #           EULADISPLAY="None"
751         else
752             trace defaulting EULADISPLAY="None"
753             EULADISPLAY="None"
754         fi
755
756
757         # **********************************************************
758         #  3. Load template files and substitute values
759         # **********************************************************
760         if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
761                 trace loading 1.0 template files
762                 local stub=`<"$autopackage_share/stub.template"` || { echo "Couldn't load stub.template"; return $ERROR_NO_STUB; }
763                 local downloader=`<"$autopackage_share/downloader.template"` || { echo "Couldn't load downloader.template"; return $ERROR_NO_DOWNLOADER; }
764         elif [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
765                 trace loading 1.2 template files
766                 local stub=`<"$autopackage_share/stub.2.template"` || { echo "Couldn't load stub.2.template"; return $ERROR_NO_STUB; }
767                 local downloader=`<"$autopackage_share/downloader.2.template"` || { echo "Couldn't load downloader.2.template"; return $ERROR_NO_DOWNLOADER; }
768         else
769                 trace loading 1.4 template files
770                 local stub=`<"$autopackage_share/stub.4.template"` || { echo "Couldn't load stub.4.template"; return $ERROR_NO_STUB; }
771                 stub=$(substituteCode "$autopackage_share/apkg-bashlib" "START COMPAREVERSIONS SIMPLE" "END COMPAREVERSIONS SIMPLE" "$stub" "%CompareVersions%")
772                 stub=$(substituteCode "$autopackage_share/apkg-bashlib" "START MESSAGE" "END MESSAGE" "$stub" "%Message%")
773                 local downloader=`<"$autopackage_share/downloader.2.template"` || { echo "Couldn't load downloader.2.template"; return $ERROR_NO_DOWNLOADER; }
774         fi
775
776         installer=$(_getInstallerTemplate)
777         if (($? != 0)); then
778                 echo "Error loading installer template"
779                 return $ERROR_NO_INSTALLER
780         fi
781        
782         if [[ -z "$autopackage_share/backend.template" ]]; then
783                 echo "backend.template doesn't exist";
784                 return $ERROR_NO_BACKEND;
785         fi
786
787         downloader=`substituteCode "$autopackage_share/apkg-funclib" "START INSTALLAUTOPACKAGE" "END INSTALLAUTOPACKAGE" "$downloader" "%InstallAutopackage%"`
788         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START YESNO" "END YESNO" "$downloader" "%YesNo%"`
789         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START STARTDOWNLOAD" "END STARTDOWNLOAD" "$downloader" "%StartDownload%"`
790         downloader=`substituteCode "$autopackage_share/apkg-funclib" "START DOWNLOADAUTOPACKAGEINFO" "END DOWNLOADAUTOPACKAGEINFO" "$downloader" "%DownloadAutopackageInfo%"`
791         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START DOWNLOADFUNCTION" "END DOWNLOADFUNCTION" "$downloader" "%DownloadFunction%"`
792         downloader=`substituteCode "$autopackage_share/apkg-funclib" "START FINISHWINDOW" "END FINISHWINDOW" "$downloader" "%FinishWindow%"`
793         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START LAUNCHINTERMINAL" "END LAUNCHINTERMINAL" "$downloader" "%LaunchInTerminal%"`
794         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START LOCATECOMMAND" "END LOCATECOMMAND" "$downloader" "%LocateCommand%"`
795         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START MESSAGE" "END MESSAGE" "$downloader" "%Message%"`
796         downloader=`substituteCode "$autopackage_share/apkg-funclib" "START AUTOSUCOMMAND" "END AUTOSUCOMMAND" "$downloader" "%AutosuCommand%"`
797         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START PUSHOPTE" "END PUSHOPTE" "$downloader" "%PushOptE%"`
798         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START POPOPTE" "END POPOPTE" "$downloader" "%PopOptE%"`
799         downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START RESOLVELINK" "END RESOLVELINK" "$downloader" "%ResolveLink%"`
800         downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START SCANLDLIBPATH" "END SCANLDLIBPATH" "$downloader" "%ScanLDLibPath%"`
801         downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START GETLIBRARYPATHS" "END GETLIBRARYPATHS" "$downloader" "%GetLibraryPaths%"`
802         downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START TESTFORLIB" "END TESTFORLIB" "$downloader" "%TestForLib%"`
803         downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START ISLIBRARY32" "END ISLIBRARY32" "$downloader" "%IsLibrary32%"`
804         trace loaded
805
806         ###### Substitute values into templates
807
808         # Sets _payload_dir and _meta_dir before package expansion; used by _retrieveLocalPackage
809         stub=$( echo "$stub" | replaceStr "%AutopackageVersion%" "$autopackage_version" )
810         stub=$( echo "$stub" | replaceStr "%RootName%" "$ROOTNAME" )
811         stub=$( echo "$stub" | replaceStr "%ShortName%" "$SHORTNAME" )
812         stub=$( echo "$stub" | replaceStr "%SoftwareVersion%" "$SOFTWAREVERSION" )
813         stub=$( echo "$stub" | replaceStr "%InterfaceVersion%" "$INTERFACEVERSION" )
814         stub=$( echo "$stub" | replaceStr "%PackageVersion%" "$PACKAGEVERSION" )
815         stub=$( echo "$stub" | replaceStr "%CPUArchitecture%" "x86" ) # Pre 1.4 packages only support x86
816         stub=$( echo "$stub" | replaceStr "%AutopackageTarget%" "$AUTOPACKAGETARGET" )
817
818         # Make the built package require the current autopackage version
819         installer=$( echo "$installer" | replaceStr "%RootName%" "$ROOTNAME" )
820
821
822         ####
823
824         # **********************************************************
825         #  3. Generate package scripts
826         # **********************************************************
827         #  3.1. Prepare script
828         # **********************************************************
829         local prep_script=$( getSection "$specfile" Prepare )
830         if [[ "$prep_script" == "" ]]; then
831             red; outn "WARNING: "; normal; out "No prep script [Prepare] found in the specfile, you might want one of these";
832         fi
833
834         # **********************************************************
835         #  3.1.1. Check for require calls
836         # **********************************************************
837         # Scan for proper "require*" and "recommend*" lines
838     echo "$prep_script" | while read; do
839
840         # skip blank and commented lines
841         if [ -z "$REPLY" ] || [[ ${REPLY:0:1} == "#" ]]; then
842             continue
843         fi
844
845         # prepare could have logic so try to capture at least space leading lines
846         local mode_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $1 }' - | tr -d "\";" | tr -d "\';"`
847         local rootname_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $2 }' - | tr -d "\";" | tr -d "\';"`
848         local version_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $3 }' - | tr -d "\";" | tr -d "\';"`
849
850         if [[ "$mode_check" == "require" ]] || [[ "$mode_check" == "recommend" ]]; then
851             if [ -n "`versionFromRootName $rootname_check`" ] || [ -z "$version_check" ]; then
852                 err "require/recommend needs an unversioned rootname and an interface version - '$REPLY'"
853                 return 1
854             else
855                 trace prepare call verified mode=$mode_check rootname=$rootname_check version=$version_check
856             fi
857         fi
858
859         if [[ "$mode_check" == "requireExact" ]] || [[ "$mode_check" == "requireAtLeast" ]] || [[ "$mode_check" == "recommendExact" ]] || [[ "$mode_check" == "recommendAtLeast" ]]; then
860             if [ -z "`versionFromRootName $rootname_check`" ] || [ -n "$version_check" ]; then
861                 err "requireExact/requireAtLeast/recommendExact/recommendAtLeast needs an versioned rootname and an interface version - '$REPLY'"
862                 return 1
863             else
864                 trace prepare call verified mode=$mode_check rootname=$rootname_check version=$version_check
865             fi
866         fi
867
868         unset mode_check rootname_check version_check
869
870     done
871
872         # Incorporate "require*" and "recommend*" lines
873         local requires=` echo "$prep_script" | awk '/^[ \t]*[require|recommend]*/ {
874                 i=1
875                 while (i < NF && $i != "#") {
876                         if ( $i == "require" || $i == "requireExact" || $i == "requireAtLeast" || $i == "recommend" || $i == "recommendExact" || $i == "recommendAtLeast" ) {
877                                 i++;
878                                 print $i;
879                         }
880                         i++;
881                 }
882         } ' | tr -d "\";" | tr -d "\';" `
883
884         # **********************************************************
885         #  3.1.2. Check for required skeletons
886         # **********************************************************
887         if [[ "$requires" != "" ]]; then
888                 # Ensure we have the needed skeleton packages
889                 i=1
890                 local requirement=` getLine "$requires" $i `
891                 local requirements=""
892                 local foundSkelFile
893                 while [[ "$requirement" != "" ]]; do
894                         requirements="$requirements $requirement"; # Add to list, this accumulates versioned root names....
895                         foundSkelFile=`_locateSkeleton "$requirement"`
896                         res=$?
897                         skels_to_copy_files="$skels_to_copy_files $foundSkelFile"
898
899                         if [[ "$res" != "0" ]]; then # and this accumulates the file refs: @gnome.org/libxml/skeleton.2
900                                 if [[ "$res" == "1" ]]; then
901                                         red; outn "FAIL: "; normal;  out "Could not locate skeleton package for '%s'" "$requirement";
902                                         normal; out "Try running svn update in the skeletons directory to get the latest files"
903                                         return $ERROR_MISSING_SKELETON;
904                                 elif [[ "$res" == "2" ]]; then
905                                         red; outn "FAIL: "; normal; out "Bad skeleton for %s, not in ASCII text format" "$requirement";
906                                         normal; out "Try running svn update in the skeletons directory to get the latest files"
907                                         return $ERROR_MISSING_SKELETON;
908                                 elif [[ "$res" == "3" ]]; then
909                                         red
910                                         out "Skeleton for %s was found, but the skeleton file has an incorrect root name (%s)" "$requirement" "$foundSkelFile"
911                                         normal
912                                         return $ERROR_MISSING_SKELETON;
913                                 fi
914                         fi
915
916                         # check sanity of skelVersionReq, code stolen from check for $AUTOPACKAGETARGET
917                         skelVersionReq=`getSectionKey "$foundSkelFile" Meta AutopackageTarget`
918                         local skel_apkgtarget_major=`getMajor "$skelVersionReq"`
919                         local skel_apkgtarget_minor=`getMinor "$skelVersionReq"`
920
921                         if [ `expr index "$skel_apkgtarget_major" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ]; then
922                                 skel_apkgtarget_major="1"
923                         fi
924
925                         if [ `expr index "$skel_apkgtarget_minor" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ] || [[ "$skel_apkgtarget_minor" == "" ]]; then
926                                 skel_apkgtarget_minor="0"
927                         fi
928
929                         if [[ "$skel_apkgtarget_major" != "" ]]; then
930                                 skelVersionReq="$skel_apkgtarget_major.$skel_apkgtarget_minor"
931                         else
932                                 skelVersionReq="1.0"
933                         fi
934
935                         if ! compareVersions $skelVersionReq $AUTOPACKAGETARGET; then
936                                 red; outn "FAIL: " ; normal; out "Skeleton for '%s' requires Autopackage API version $skelVersionReq. Increase AutopackageTarget in your specfile to $skelVersionReq." "$requirement"
937                                 return $ERROR_SKELETON_API_MISMATCH
938                         fi
939
940                         (( i++ ));
941                         trace added requirement $requirement, `_locateSkeleton $requirement`
942                         requirement=` getLine "$requires" $i `;
943                 done
944         fi
945         if [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
946                 prep_script=$(_getBackendTemplate "prep" "$prep_script")
947         fi
948
949         # **********************************************************
950         #  3.2. Uninstall script
951         # **********************************************************