CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
Prefer archive_entry_mode() over archive_entry_stat().
[pkgutils-cross.git] / pkgmk.in
CommitLineData
9ac667e6
SR
1#!/bin/bash
2#
3# pkgutils
4#
5# Copyright (c) 2000-2005 Per Liden
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20# USA.
21#
22
23info() {
24 echo "=======> $1"
25}
26
27warning() {
e55714dd 28 info "WARNING: $1" >&2
9ac667e6
SR
29}
30
31error() {
e55714dd 32 info "ERROR: $1" >&2
9ac667e6
SR
33}
34
35get_filename() {
36 local FILE="`echo $1 | sed 's|^.*://.*/||g'`"
37
38 if [ "$FILE" != "$1" ]; then
39 FILE="$PKGMK_SOURCE_DIR/$FILE"
40 fi
41
42 echo $FILE
43}
44
45check_pkgfile() {
46 if [ ! "$name" ]; then
47 error "Variable 'name' not specified in $PKGMK_PKGFILE."
48 exit 1
49 elif [ ! "$version" ]; then
50 error "Variable 'version' not specified in $PKGMK_PKGFILE."
51 exit 1
52 elif [ ! "$release" ]; then
53 error "Variable 'release' not specified in $PKGMK_PKGFILE."
54 exit 1
55 elif [ "`type -t build`" != "function" ]; then
56 error "Function 'build' not specified in $PKGMK_PKGFILE."
57 exit 1
58 fi
59}
60
61check_directory() {
62 if [ ! -d $1 ]; then
63 error "Directory '$1' does not exist."
64 exit 1
65 elif [ ! -w $1 ]; then
66 error "Directory '$1' not writable."
67 exit 1
68 elif [ ! -x $1 ] || [ ! -r $1 ]; then
69 error "Directory '$1' not readable."
70 exit 1
71 fi
72}
73
74download_file() {
75 info "Downloading '$1'."
76
77 if [ ! "`type -p wget`" ]; then
78 error "Command 'wget' not found."
79 exit 1
80 fi
81
82 LOCAL_FILENAME=`get_filename $1`
83 LOCAL_FILENAME_PARTIAL="$LOCAL_FILENAME.partial"
84 DOWNLOAD_CMD="--passive-ftp --no-directories --tries=3 --waitretry=3 \
85 --directory-prefix=$PKGMK_SOURCE_DIR --output-document=$LOCAL_FILENAME_PARTIAL $1"
86
87 if [ -f "$LOCAL_FILENAME_PARTIAL" ]; then
88 info "Partial download found, trying to resume"
89 RESUME_CMD="-c"
90 fi
91
92 while true; do
93 wget $RESUME_CMD $DOWNLOAD_CMD
94 error=$?
95 if [ $error != 0 ] && [ "$RESUME_CMD" ]; then
96 info "Partial download failed, restarting"
97 rm -f "$LOCAL_FILENAME_PARTIAL"
98 RESUME_CMD=""
99 else
100 break
101 fi
102 done
103
104 if [ $error != 0 ]; then
105 error "Downloading '$1' failed."
106 exit 1
107 fi
108
109 mv -f "$LOCAL_FILENAME_PARTIAL" "$LOCAL_FILENAME"
110}
111
112download_source() {
113 local FILE LOCAL_FILENAME
114
115 for FILE in ${source[@]}; do
116 LOCAL_FILENAME=`get_filename $FILE`
117 if [ ! -e $LOCAL_FILENAME ]; then
118 if [ "$LOCAL_FILENAME" = "$FILE" ]; then
119 error "Source file '$LOCAL_FILENAME' not found (can not be downloaded, URL not specified)."
120 exit 1
121 else
122 if [ "$PKGMK_DOWNLOAD" = "yes" ]; then
123 download_file $FILE
124 else
125 error "Source file '$LOCAL_FILENAME' not found (use option -d to download)."
126 exit 1
127 fi
128 fi
129 fi
130 done
131}
132
133unpack_source() {
134 local FILE LOCAL_FILENAME COMMAND
135
136 for FILE in ${source[@]}; do
137 LOCAL_FILENAME=`get_filename $FILE`
138 case $LOCAL_FILENAME in
139 *.tar.gz|*.tar.Z|*.tgz)
140 COMMAND="tar -C $SRC --use-compress-program=gzip -xf $LOCAL_FILENAME" ;;
141 *.tar.bz2)
142 COMMAND="tar -C $SRC --use-compress-program=bzip2 -xf $LOCAL_FILENAME" ;;
143 *.zip)
144 COMMAND="unzip -qq -o -d $SRC $LOCAL_FILENAME" ;;
145 *)
146 COMMAND="cp $LOCAL_FILENAME $SRC" ;;
147 esac
148
149 echo "$COMMAND"
150
151 $COMMAND
152
153 if [ $? != 0 ]; then
154 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
155 rm -rf $PKGMK_WORK_DIR
156 fi
157 error "Building '$TARGET' failed."
158 exit 1
159 fi
160 done
161}
162
163make_md5sum() {
164 local FILE LOCAL_FILENAMES
165
166 if [ "$source" ]; then
167 for FILE in ${source[@]}; do
168 LOCAL_FILENAMES="$LOCAL_FILENAMES `get_filename $FILE`"
169 done
170
171 md5sum $LOCAL_FILENAMES | sed -e 's| .*/| |' | sort -k 2
172 fi
173}
174
175make_footprint() {
176 pkginfo --footprint $TARGET | \
177 sed "s|\tlib/modules/`uname -r`/|\tlib/modules/<kernel-version>/|g" | \
178 sort -k 3
179}
180
181check_md5sum() {
182 local FILE="$PKGMK_WORK_DIR/.tmp"
183
184 cd $PKGMK_ROOT
185
186 if [ -f $PKGMK_MD5SUM ]; then
187 make_md5sum > $FILE.md5sum
188 sort -k 2 $PKGMK_MD5SUM > $FILE.md5sum.orig
189 diff -w -t -U 0 $FILE.md5sum.orig $FILE.md5sum | \
190 sed '/^@@/d' | \
191 sed '/^+++/d' | \
192 sed '/^---/d' | \
193 sed 's/^+/NEW /g' | \
194 sed 's/^-/MISSING /g' > $FILE.md5sum.diff
195 if [ -s $FILE.md5sum.diff ]; then
196 error "Md5sum mismatch found:"
e55714dd 197 cat $FILE.md5sum.diff >&2
9ac667e6
SR
198
199 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
200 rm -rf $PKGMK_WORK_DIR
201 fi
202
203 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
204 error "Md5sum not ok."
205 exit 1
206 fi
207
208 error "Building '$TARGET' failed."
209 exit 1
210 fi
211 else
212 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
213 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
214 rm -rf $PKGMK_WORK_DIR
215 fi
216 info "Md5sum not found."
217 exit 1
218 fi
219
220 warning "Md5sum not found, creating new."
221 make_md5sum > $PKGMK_MD5SUM
222 fi
223
224 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
225 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
226 rm -rf $PKGMK_WORK_DIR
227 fi
228 info "Md5sum ok."
229 exit 0
230 fi
231}
232
233strip_files() {
234 local FILE FILTER
235
236 cd $PKG
237
238 if [ -f $PKGMK_ROOT/$PKGMK_NOSTRIP ]; then
239 FILTER="grep -v -f $PKGMK_ROOT/$PKGMK_NOSTRIP"
240 else
241 FILTER="cat"
242 fi
243
244 find . -type f -printf "%P\n" | $FILTER | while read FILE; do
b0bbde50
SR
245 case $(file -b "$FILE") in
246 *ELF*executable*not\ stripped)
9ac667e6 247 strip --strip-all "$FILE"
b0bbde50
SR
248 ;;
249 *ELF*shared\ object*not\ stripped)
9ac667e6 250 strip --strip-unneeded "$FILE"
b0bbde50
SR
251 ;;
252 current\ ar\ archive)
9ac667e6 253 strip --strip-debug "$FILE"
b0bbde50 254 esac
9ac667e6
SR
255 done
256}
257
258compress_manpages() {
259 local FILE DIR TARGET
260
261 cd $PKG
262
263 find . -type f -path "*/man/man*/*" | while read FILE; do
264 if [ "$FILE" = "${FILE%%.gz}" ]; then
265 gzip -9 "$FILE"
266 fi
267 done
268
269 find . -type l -path "*/man/man*/*" | while read FILE; do
270 TARGET=`readlink -n "$FILE"`
271 TARGET="${TARGET##*/}"
272 TARGET="${TARGET%%.gz}.gz"
273 rm -f "$FILE"
274 FILE="${FILE%%.gz}.gz"
275 DIR=`dirname "$FILE"`
276
277 if [ -e "$DIR/$TARGET" ]; then
278 ln -sf "$TARGET" "$FILE"
279 fi
280 done
281}
282
283check_footprint() {
284 local FILE="$PKGMK_WORK_DIR/.tmp"
285
286 cd $PKGMK_ROOT
287
288 if [ -f $TARGET ]; then
289 make_footprint > $FILE.footprint
290 if [ -f $PKGMK_FOOTPRINT ]; then
291 sort -k 3 $PKGMK_FOOTPRINT > $FILE.footprint.orig
292 diff -w -t -U 0 $FILE.footprint.orig $FILE.footprint | \
293 sed '/^@@/d' | \
294 sed '/^+++/d' | \
295 sed '/^---/d' | \
296 sed 's/^+/NEW /g' | \
297 sed 's/^-/MISSING /g' > $FILE.footprint.diff
298 if [ -s $FILE.footprint.diff ]; then
299 error "Footprint mismatch found:"
e55714dd 300 cat $FILE.footprint.diff >&2
9ac667e6
SR
301 BUILD_SUCCESSFUL="no"
302 fi
303 else
304 warning "Footprint not found, creating new."
305 mv $FILE.footprint $PKGMK_FOOTPRINT
306 fi
307 else
308 error "Package '$TARGET' was not found."
309 BUILD_SUCCESSFUL="no"
310 fi
311}
312
313build_package() {
314 local BUILD_SUCCESSFUL="no"
315
316 export PKG="$PKGMK_WORK_DIR/pkg"
317 export SRC="$PKGMK_WORK_DIR/src"
318 umask 022
319
320 cd $PKGMK_ROOT
321 rm -rf $PKGMK_WORK_DIR
322 mkdir -p $SRC $PKG
323
324 if [ "$PKGMK_IGNORE_MD5SUM" = "no" ]; then
325 check_md5sum
326 fi
327
328 if [ "$UID" != "0" ]; then
329 warning "Packages should be built as root."
330 fi
331
332 info "Building '$TARGET'."
333
334 unpack_source
335
336 cd $SRC
337 (set -e -x ; build)
338
339 if [ $? = 0 ]; then
340 if [ "$PKGMK_NO_STRIP" = "no" ]; then
341 strip_files
342 fi
343
344 compress_manpages
345
346 cd $PKG
347 info "Build result:"
348 tar czvvf $TARGET *
349
350 if [ $? = 0 ]; then
351 BUILD_SUCCESSFUL="yes"
352
353 if [ "$PKGMK_IGNORE_FOOTPRINT" = "yes" ]; then
354 warning "Footprint ignored."
355 else
356 check_footprint
357 fi
358 fi
359 fi
360
361 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
362 rm -rf $PKGMK_WORK_DIR
363 fi
364
365 if [ "$BUILD_SUCCESSFUL" = "yes" ]; then
366 info "Building '$TARGET' succeeded."
367 else
368 if [ -f $TARGET ]; then
369 touch -r $PKGMK_ROOT/$PKGMK_PKGFILE $TARGET &> /dev/null
370 fi
371 error "Building '$TARGET' failed."
372 exit 1
373 fi
374}
375
376install_package() {
377 local COMMAND
378
379 info "Installing '$TARGET'."
380
381 if [ "$PKGMK_INSTALL" = "install" ]; then
382 COMMAND="pkgadd $TARGET"
383 else
384 COMMAND="pkgadd -u $TARGET"
385 fi
386
387 cd $PKGMK_ROOT
388 echo "$COMMAND"
389 $COMMAND
390
391 if [ $? = 0 ]; then
392 info "Installing '$TARGET' succeeded."
393 else
394 error "Installing '$TARGET' failed."
395 exit 1
396 fi
397}
398
399recursive() {
400 local ARGS FILE DIR
401
402 ARGS=`echo "$@" | sed -e "s/--recursive//g" -e "s/-r//g"`
403
404 for FILE in `find $PKGMK_ROOT -name $PKGMK_PKGFILE | sort`; do
405 DIR="`dirname $FILE`/"
406 if [ -d $DIR ]; then
407 info "Entering directory '$DIR'."
408 (cd $DIR && $PKGMK_COMMAND $ARGS)
409 info "Leaving directory '$DIR'."
410 fi
411 done
412}
413
414clean() {
415 local FILE LOCAL_FILENAME
416
417 if [ -f $TARGET ]; then
418 info "Removing $TARGET"
419 rm -f $TARGET
420 fi
421
422 for FILE in ${source[@]}; do
423 LOCAL_FILENAME=`get_filename $FILE`
424 if [ -e $LOCAL_FILENAME ] && [ "$LOCAL_FILENAME" != "$FILE" ]; then
425 info "Removing $LOCAL_FILENAME"
426 rm -f $LOCAL_FILENAME
427 fi
428 done
429}
430
431update_footprint() {
432 if [ ! -f $TARGET ]; then
433 error "Unable to update footprint. File '$TARGET' not found."
434 exit 1
435 fi
436
437 make_footprint > $PKGMK_FOOTPRINT
438 touch $TARGET
439
440 info "Footprint updated."
441}
442
443build_needed() {
444 local FILE RESULT
445
446 RESULT="yes"
447 if [ -f $TARGET ]; then
448 RESULT="no"
449 for FILE in $PKGMK_PKGFILE ${source[@]}; do
450 FILE=`get_filename $FILE`
451 if [ ! -e $FILE ] || [ ! $TARGET -nt $FILE ]; then
452 RESULT="yes"
453 break
454 fi
455 done
456 fi
457
458 echo $RESULT
459}
460
461interrupted() {
462 echo ""
463 error "Interrupted."
464
465 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
466 rm -rf $PKGMK_WORK_DIR
467 fi
468
469 exit 1
470}
471
472print_help() {
473 echo "usage: `basename $PKGMK_COMMAND` [options]"
474 echo "options:"
475 echo " -i, --install build and install package"
476 echo " -u, --upgrade build and install package (as upgrade)"
477 echo " -r, --recursive search for and build packages recursively"
478 echo " -d, --download download missing source file(s)"
479 echo " -do, --download-only do not build, only download missing source file(s)"
480 echo " -utd, --up-to-date do not build, only check if package is up to date"
481 echo " -uf, --update-footprint update footprint using result from last build"
482 echo " -if, --ignore-footprint build package without checking footprint"
483 echo " -um, --update-md5sum update md5sum"
484 echo " -im, --ignore-md5sum build package without checking md5sum"
485 echo " -cm, --check-md5sum do not build, only check md5sum"
486 echo " -ns, --no-strip do not strip executable binaries or libraries"
487 echo " -f, --force build package even if it appears to be up to date"
488 echo " -c, --clean remove package and downloaded files"
489 echo " -kw, --keep-work keep temporary working directory"
490 echo " -cf, --config-file <file> use alternative configuration file"
491 echo " -v, --version print version and exit "
492 echo " -h, --help print help and exit"
493}
494
495parse_options() {
496 while [ "$1" ]; do
497 case $1 in
498 -i|--install)
499 PKGMK_INSTALL="install" ;;
500 -u|--upgrade)
501 PKGMK_INSTALL="upgrade" ;;
502 -r|--recursive)
503 PKGMK_RECURSIVE="yes" ;;
504 -d|--download)
505 PKGMK_DOWNLOAD="yes" ;;
506 -do|--download-only)
507 PKGMK_DOWNLOAD="yes"
508 PKGMK_DOWNLOAD_ONLY="yes" ;;
509 -utd|--up-to-date)
510 PKGMK_UP_TO_DATE="yes" ;;
511 -uf|--update-footprint)
512 PKGMK_UPDATE_FOOTPRINT="yes" ;;
513 -if|--ignore-footprint)
514 PKGMK_IGNORE_FOOTPRINT="yes" ;;
515 -um|--update-md5sum)
516 PKGMK_UPDATE_MD5SUM="yes" ;;
517 -im|--ignore-md5sum)
518 PKGMK_IGNORE_MD5SUM="yes" ;;
519 -cm|--check-md5sum)
520 PKGMK_CHECK_MD5SUM="yes" ;;
521 -ns|--no-strip)
522 PKGMK_NO_STRIP="yes" ;;
523 -f|--force)
524 PKGMK_FORCE="yes" ;;
525 -c|--clean)
526 PKGMK_CLEAN="yes" ;;
527 -kw|--keep-work)
528 PKGMK_KEEP_WORK="yes" ;;
529 -cf|--config-file)
530 if [ ! "$2" ]; then
531 echo "`basename $PKGMK_COMMAND`: option $1 requires an argument"
532 exit 1
533 fi
534 PKGMK_CONFFILE="$2"
535 shift ;;
536 -v|--version)
537 echo "`basename $PKGMK_COMMAND` (pkgutils) $PKGMK_VERSION"
538 exit 0 ;;
539 -h|--help)
540 print_help
541 exit 0 ;;
542 *)
543 echo "`basename $PKGMK_COMMAND`: invalid option $1"
544 exit 1 ;;
545 esac
546 shift
547 done
548}
549
550main() {
551 local FILE TARGET
552
553 parse_options "$@"
554
555 if [ "$PKGMK_RECURSIVE" = "yes" ]; then
556 recursive "$@"
557 exit 0
558 fi
559
560 for FILE in $PKGMK_PKGFILE $PKGMK_CONFFILE; do
561 if [ ! -f $FILE ]; then
562 error "File '$FILE' not found."
563 exit 1
564 fi
565 . $FILE
566 done
567
568 check_directory "$PKGMK_SOURCE_DIR"
569 check_directory "$PKGMK_PACKAGE_DIR"
570 check_directory "`dirname $PKGMK_WORK_DIR`"
571
572 check_pkgfile
573
574 TARGET="$PKGMK_PACKAGE_DIR/$name#$version-$release.pkg.tar.gz"
575
576 if [ "$PKGMK_CLEAN" = "yes" ]; then
577 clean
578 exit 0
579 fi
580
581 if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then
582 update_footprint
583 exit 0
584 fi
585
586 if [ "$PKGMK_UPDATE_MD5SUM" = "yes" ]; then
587 download_source
588 make_md5sum > $PKGMK_MD5SUM
589 info "Md5sum updated."
590 exit 0
591 fi
592
593 if [ "$PKGMK_DOWNLOAD_ONLY" = "yes" ]; then
594 download_source
595 exit 0
596 fi
597
598 if [ "$PKGMK_UP_TO_DATE" = "yes" ]; then
599 if [ "`build_needed`" = "yes" ]; then
600 info "Package '$TARGET' is not up to date."
601 else
602 info "Package '$TARGET' is up to date."
603 fi
604 exit 0
605 fi
606
607 if [ "`build_needed`" = "no" ] && [ "$PKGMK_FORCE" = "no" ] && [ "$PKGMK_CHECK_MD5SUM" = "no" ]; then
608 info "Package '$TARGET' is up to date."
609 else
610 download_source
611 build_package
612 fi
613
614 if [ "$PKGMK_INSTALL" != "no" ]; then
615 install_package
616 fi
617
618 exit 0
619}
620
621trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
622
623export LC_ALL=POSIX
624
625readonly PKGMK_VERSION="#VERSION#"
626readonly PKGMK_COMMAND="$0"
627readonly PKGMK_ROOT="$PWD"
628
629PKGMK_CONFFILE="/etc/pkgmk.conf"
630PKGMK_PKGFILE="Pkgfile"
631PKGMK_FOOTPRINT=".footprint"
632PKGMK_MD5SUM=".md5sum"
633PKGMK_NOSTRIP=".nostrip"
634
635PKGMK_SOURCE_DIR="$PWD"
636PKGMK_PACKAGE_DIR="$PWD"
637PKGMK_WORK_DIR="$PWD/work"
638
639PKGMK_INSTALL="no"
640PKGMK_RECURSIVE="no"
641PKGMK_DOWNLOAD="no"
642PKGMK_DOWNLOAD_ONLY="no"
643PKGMK_UP_TO_DATE="no"
644PKGMK_UPDATE_FOOTPRINT="no"
645PKGMK_IGNORE_FOOTPRINT="no"
646PKGMK_FORCE="no"
647PKGMK_KEEP_WORK="no"
648PKGMK_UPDATE_MD5SUM="no"
649PKGMK_IGNORE_MD5SUM="no"
650PKGMK_CHECK_MD5SUM="no"
651PKGMK_NO_STRIP="no"
652PKGMK_CLEAN="no"
653
654main "$@"
655
656# End of file