jw-pkg/scripts/pkg.sh
Jan Lindemann 97cc7fbecd
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m57s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 5m11s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m34s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m48s
CI / Packaging test (push) Successful in 0s
pkg.sh: Fix chown and chmod lines in generated postinst
The postinst generator looks up the install log line of each file with a
regex grep on the file path, and the dots of the path match any character.
When the grep returns several lines, milk_install_log_spec_attr() passes
the extra lines through, so the emitted chown and chmod commands split
across lines, dpkg -i reports errors for the fragments, and the owner and
mode of the file are not applied.

Match the end of the log line against the file path literally and take the
first match. The install log line ends in the file path, but may carry a
build prefix before it, so the literal comparison of the tail of the line
selects exactly the line of the file, for plain and %config entries alike.

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v1.4.0
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-10-27 07:02:37 +01:00

1337 lines
27 KiB
Shell

#!/bin/bash
log()
{
printf '%s\n' "$*"
}
goodbye()
{
:
rm -f $tmp_mkdef_sh scm_status.tmp
}
quit()
{
goodbye
exit $1
}
usage()
{
cat << EOT | sed 's/^ |//'
|usage: $myname cmd
EOT
[ "$1" ] && {
quit $1
}
}
fatal()
{
log "$*"
log "Giving up."
quit 1
}
platform_info()
{
/usr/bin/python3 $JWB_SCRIPT_DIR/jw-pkg.py platform info --format "$1"
}
get_os()
{
[ "$__get_os" ] || __get_os=`platform_info '%{id}-%{codename}'`
echo $__get_os
}
cfg_section()
{
ini_section "$inifile" "$@"
}
scm_commit()
{
case $SCM in
cvs)
cvs commit "$@"
;;
git)
git commit -uno "$@"
;;
*)
fatal "tried to commit with unknown source code management tool $SCM"
;;
esac
}
platform()
{
echo `get_os`/$PKG_ARCH
}
abspath()
{
(cd $1; /bin/pwd)
}
read_map()
{
cmd_version -p `platform` "$@" read | sed 's/-dev//'
}
write_map()
{
cmd_version -p `platform` $1 write $2
}
find_path()
{
local p
for p in "$@"; do
[ -e "$p" ] && {
echo $p
return 0
}
done
fatal "none of the paths \"$*\" exists"
}
scm_files()
{
(
cd $TOPDIR
/bin/bash $JWB_SCRIPT_DIR/scm.sh ls-files "$@"
)
}
calculate_hash()
{
local h
h=`(
set -o pipefail
cd $TOPDIR
scm_files -s -z | \
grep -vz "CHANGES\|VERSION\|HASH\|MD5SUMS\|RELEASES" | \
md5sum | sed 's/ .*//'
)` || fatal "failed to calculate source hash"
[ -n "$h" ] || fatal "failed to calculate source hash"
echo $h
}
check_scm()
{
if [ -d .git ]; then
log + checking git
git pull --no-edit || fatal "git pull failed, giving up"
git submodule update --init --recursive || fatal "git submodule update failed, giving up"
git status --porcelain | grep -v '^??' | grep -q . && {
git status
fatal "git has locally modified files, giving up"
}
else
log + checking cvs
cvs update -dP
cvs status > scm_status.tmp 2>&1
if [ $? != 0 ]; then
cat scm_status.tmp
fatal "\n======== cvs status failed, giving up."
fi
grep -qi "locally modified" scm_status.tmp && \
fatal "cvs copy has locally modified files, giving up"
grep -qi "needs" scm_status.tmp && \
fatal "+ cvs copy is out-of-date, giving up"
fi
}
check_cwd()
{
pwd | grep -q $HOME/local/src
}
create_empty_dir()
{
[ $# != 2 ] && \
fatal "Unable to create empty directory \"$*\"."
local dir="$1"
shift
local desc="$@"
mkdir -p "$dir"
[ -w "$dir" ] ||
fatal "No write-access to $desc \"$dir\""
[ `ls "$dir" | wc -l` -eq 0 ] ||
fatal "$desc \"$dir\" isn't empty"
}
increase_build_no()
{
local build_no=`echo $1 | sed 's/.*-\([0-9]\+\)\(-dev\)*/\1/'`
build_no=`expr $build_no + 1`
echo $1 | sed "s/-\([0-9]\+\)\(-dev\)*/-$build_no\2/"
}
check_next_version()
{
local v=`read_map $TOPDIR/VERSION | sed 's/-dev//'`
local n=`read_map -n $TOPDIR/RELEASES | sed 's/-dev//'`
if [ "$n" != "$v" ]; then
echo "+ $PKG_PROJECT version is already at $v, no need to increase for release" >&2
echo $v
return
fi
local h=`calculate_hash`
[ -n "$h" ] || fatal "failed to calculate source hash"
if [ ! -f $TOPDIR/HASH ]; then
echo "+ $PKG_PROJECT has no HASH file, needs release" >&2
echo $v
return
fi
if ! read_map $TOPDIR/HASH | grep -q $h; then
echo "+ $PKG_PROJECT has no matching HASH value, needs release" >&2
increase_build_no $v
return
fi
echo "+ $PKG_PROJECT has unchanged source" >&2
if [ "$reinstall_check_failed" = 1 ]; then
echo "version $v is uninstallable, needs release" >&2
increase_build_no $v
return
fi
if [ "$reinstall_check_succeeded" = 1 ]; then
echo $v
return
fi
if ! check_pkg_reinstall >&2; then
echo "version $v is uninstallable, needs release" >&2
increase_build_no $v
return
fi
echo "version $v doesn't match any release criteria, not releasing" >&2
echo $v
}
check_pkg_install()
{
[ "$1" = -c ] && {
shift
[ ! -f "$1" ] && return 0
}
local sudo
[ "$UID" = 0 ] || sudo=/usr/bin/sudo
echo "+ installing $1"
$sudo $RPM -U $1 || {
echo "failed to install $1"
return 1
}
}
check_pkg_reinstall()
{
local v=`read_map $TOPDIR/VERSION`
local s
for s in devel run; do
if $RPM -q $PKG_PROJECT-$s > /dev/null 2>&1 ; then
echo + removing $PKG_PROJECT-$s
sudo $RPM -e $PKG_PROJECT-$s --nodeps --allmatches || {
echo "failed to uninstall $PKG_PROJECT-$s, ignored"
}
fi
done
local suffix
case "$PKG_FORMAT" in
rpm)
suffix=-$v.$PKG_ARCH.rpm
;;
*)
suffix=_$v""_$PKG_ARCH.deb
;;
esac
check_pkg_install $TOPDIR/$DIST_PKG_DIR/$PKG_PROJECT-run$suffix || return 1
check_pkg_install -c $TOPDIR/$DIST_PKG_DIR/$PKG_PROJECT-devel$suffix || return 1;
}
check_release_is_current()
{
local reinstall_pkg=
local next=`check_next_version`
local v=`read_map $TOPDIR/VERSION`
set -- `getopt 'r' $*`
while [ "$1" != -- ] ; do
case "$1" in
-r)
reinstall_pkg=1
;;
esac
shift
done
shift
if ! read_map -n $TOPDIR/RELEASES | grep -Fq $next; then
echo "next version $next is not in RELEASES, needs release" >&2
return 1
fi
if [ "$reinstall_pkg" ]; then
if ! check_pkg_reinstall; then
echo "version $v is uninstallable, needs release" >&2
reinstall_check_failed=1
return 1
fi
reinstall_check_succeeded=1
fi
return 0
}
check_update_version()
{
local comment="Start version"
set -- `getopt 'c:' "$@"`
while [ "$1" != -- ] ; do
case "$1" in
-c)
comment="$2"
shift
esac
shift
done
shift
(
cd $TOPDIR
local v=`read_map VERSION`
local next=`check_next_version`
[ "$next" ] || fatal "Failed to get next version."
if [ "$next" != "$v" ]; then
echo "$next-dev" > VERSION
scm_commit -m "$comment: $next" VERSION
return 0
fi
return 1
)
}
cmd_version()
{
cmd_version_usage()
{
cat <<- EOT | sed 's/ |//'
|usage: $myname version filename cmd [args]
EOT
[ "$1" ] && exit $1
}
cmd_version_strip_dev_dummy()
{
cat
}
cmd_version_strip_dev_real()
{
sed 's/-dev//'
}
# -- here we go
local strip_dev=cmd_version_strip_dev_dummy
local platform_patt="\(^debian-[0-9.]\+\|^suse-\([0-9.]\+\|tumbleweed\)\)/\(i.86\|x86_64\|amd64\): *"
local no_compat=
local platform=`platform`
[ $# -lt 2 ] && cmd_version_usage 1
set -- `getopt 'hsnp:' "$@"`
while [ "$1" != -- ] ; do
case "$1" in
-n)
no_compat=true;;
-s)
strip_dev=cmd_version_strip_dev_real;;
-p)
platform="$2"; shift;;
-h)
cmd_version_usage 0;;
*)
cmd_version_usage 1;;
esac
shift
done
shift
local file="$1"
shift
local cmd=$1
shift
case $cmd in
read)
local p=`echo $platform | sed 's%/%\\\/%g'`
local v=`sed "/$p:/ !d; s/$p: *//" $file`
[ "$v" ] && {
echo "$v" | $strip_dev
return
}
[ "$no_compat" = true ] && {
return
}
grep -q "$platform_patt" $file || {
cat $file | $strip_dev
return
}
local pp=`echo $platform_patt | sed 's%/%\\\/%g'`
sed "/$pp/ !d; s/$pp//; 2,$ d" $file | $strip_dev
;;
write)
local val=$1
local p=$platform
[ -f $file ] || {
echo "$p: $val" > $file
return
}
grep -q "$platform_patt" $file || {
echo "$p: $val" > $file
return
}
grep -q "^$p:" $file || {
echo "$p: $val" >> $file
return
}
p=`echo $p | sed 's%/%\\\/%g'`
val=`echo $val | sed 's%/%\\\/%g'`
sed "s/$p:.*/$p: $val/" $file > $file.tmp
mv $file.tmp $file
;;
*)
echo unknown command $cmd >&2
cmd_version_usage 1;;
esac
}
build_pkg()
{
local scm_files_opts=""
eval set -- `getopt -o a -l include-vcs-files -- "$@"`
while [ "$1" != -- ]; do
case $1 in
-a|--include-vcs-files)
scm_files_opts="$scm_files_opts -a"
;;
*)
echo -e "Unexpected argument >$1<\n" >&2
exit 1
;;
esac
shift
done
shift
set -e
local version=`read_map $TOPDIR/VERSION | sed 's/-dev//'`
local src_base=$PKG_PROJECT-$version
local src_tree=$DIST_SRC_DIR/$src_base
local tar_archive=$src_base.tar.bz2
local tar_archive_orig=$src_base.orig.tar.bz2
local distribution=`get_os`
local rpm_requires_run="$PKG_REQUIRES_RUN"
local rpm_recommends_run="$PKG_RECOMMENDS_RUN"
local rpm_requires_devel="$PKG_REQUIRES_DEVEL"
local rpm_conflicts_run="$PKG_CONFLICTS_RUN"
local rpm_conflicts_devel="$PKG_CONFLICTS_DEVEL"
local rpm_provides_run="$PKG_PROVIDES_RUN"
local rpm_provides_devel="$PKG_PROVIDES_DEVEL"
# --- create source directory tree
create_empty_dir $src_tree "Source files compilation directory"
# --- copy source files over
scm_files $scm_files_opts |
grep -v VERSION |
cpio -o -H newc |
( cd $src_tree; cpio -m --make-directories -i)
echo $version > $src_tree/VERSION
local pkgfmt
for pkgfmt in $PKG_FORMAT; do
local deffmt
case $pkgfmt in
rpm)
# historical mess:
# pkg.sh -> mkspec-wrapper.sh -> create-mkspec.sh -> mkspec.sh -> spec -> rpmbuild spec > /var/tmp/xy.sh -> pkg.sh milk-install-log
deffmt=spec;;
debian|deb)
deffmt=debian;;
*)
;;
esac
# --- generate spec file
local mkdef_sh=$TOPDIR/make/mk$deffmt.sh
local mkdef_wrapper_sh=$JWB_SCRIPT_DIR/mkspec-wrapper.sh
[ ! -r $mkdef_wrapper_sh ] && \
fatal "Failed to read package definition deffmt wrapper script \"$mkdef_wrapper_sh\"."
scm_files | grep -q make/mk$deffmt.sh || {
local create_mkdef_sh=$JWB_SCRIPT_DIR/create-mk$deffmt.sh
[ ! -r "$PROJECT_DESCR_FILE" ] && \
fatal "Failed to read project description file \"$PROJECT_DESCR_FILE\"."
[ ! -r "$create_mkdef_sh" ] && \
fatal "Failed to read package build definition creation script \"$create_mkdef_sh\"."
PATH=$JWB_SCRIPT_DIR:$PATH /bin/bash $create_mkdef_sh $PROJECT_DESCR_FILE > $mkdef_sh.tmp
mv $mkdef_sh.tmp $mkdef_sh
tmp_mkdef_sh="$tmp_mkdef_sh $mkdef_sh"
}
mkdef_sh=`readlink -f $mkdef_sh`
mkdef_wrapper_sh=`readlink -f $mkdef_wrapper_sh`
(
cd $src_tree
PATH=$JWB_SCRIPT_DIR:$PATH /bin/bash $mkdef_wrapper_sh $mkdef_sh \
-V $version \
-S $tar_archive \
-N $PKG_PROJECT \
-R "$rpm_requires_run" \
-E "$rpm_recommends_run" \
-X "$rpm_conflicts_run" \
-D "$rpm_requires_devel" \
-Y "$rpm_conflicts_devel" \
--provides-run "$rpm_provides_run" \
--provides-devel "$rpm_provides_devel" \
-P $PROJECT \
-d $distribution \
> $PKG_PROJECT.$deffmt
)
done
# --- tar up source directory tree
create_empty_dir $DIST_PKG_DIR "Package directory"
tar --anchored -czvf $DIST_PKG_DIR/$tar_archive -C $DIST_SRC_DIR `basename $src_tree`
case "$PKG_FORMAT" in
rpm)
# --- build RPMs and copy them to source directory
local rpmbuild_root=${RPMBUILD_ROOT:-$HOME/rpmbuild}
mkdir -p $rpmbuild_root
rpmbuild_root=$(readlink -f $rpmbuild_root)
local rpmbuild_srpms=$rpmbuild_root/SRPMS
local rpmbuild_rpms=$rpmbuild_root/RPMS/$PKG_ARCH
rpmbuild --define "_topdir $rpmbuild_root" -ta $DIST_PKG_DIR/$tar_archive
cp $rpmbuild_srpms/$src_base.src.rpm $DIST_PKG_DIR/
cp $rpmbuild_rpms/$PKG_PROJECT-*-$version.$PKG_ARCH.rpm $DIST_PKG_DIR/
;;
*)
#exit
#cp $DIST_PKG_DIR/$tar_archive $src_tree/../$tar_archive_orig
(
local mod_script_dir=`readlink -f $JWB_SCRIPT_DIR`
cd $src_tree
#export ENV_PREFIX=`readlink -f $TOPDIR`/$DIST_INST_DIR
#export INSTALL_LOG=blah
#strace -f -s 128 -o /tmp/strace.out debuild --no-tgz-check --prepend-path=$mod_script_dir -us -uc
debuild --no-tgz-check --prepend-path=$mod_script_dir -us -uc
)
cp $DIST_SRC_DIR/*.deb $DIST_PKG_DIR/
;;
esac
}
upload_file()
{
local quiet=false
if [ "$1" = -q ]; then
quiet=true
shift
fi
local f="$1"
local t="$2"
[ -f $DIST_PKG_DIR/$f ] || {
if [ "$quiet" = true ]; then return 0; fi
"+ $DIST_PKG_DIR/$f doesn't exist, can't upload"
return 1
}
local os_name=`get_os | sed 's/-.*//'`
local os_version=`get_os | sed 's/[^-]\+-//'`
local target_base=rsync_ssh://root@pkg.janware.com:/srv/dav/pub/packages/linux/$os_name/$os_version
[ "$upload_urlbase" ] && target_base="$upload_urlbase"
local upload_attrib=644:755:`id -un`.207
[ "$upload_file_attrib" ] && upload_attrib="$upload_file_attrib"
local target
case "$t" in
tgz)
target=$target_base/$t/$f:$upload_attrib
;;
src)
case $os_name in
centos)
target=$target_base/Source/SPackages/$f:$upload_attrib
#/srv/ftp/pub/packages/jw-foss/centos/7/Source/SPackages/tecla-1.6.3-7.1.src.rpm
;;
*)
target=$target_base/rpm/$t/$f:$upload_attrib
#/srv/ftp/pub/packages/jw-foss/suse/tumbleweed/rpm/src/jw-pkg-1.0.0-74.src.rpm
;;
esac
;;
*)
case $os_name in
centos)
target=$target_base/$t/Packages/$f:$upload_attrib
#/srv/ftp/pub/packages/jw-foss/centos/7/x86_64/Packages/tecla-devel-1.6.3-7.1.x86_64.rpm
;;
*)
target=$target_base/rpm/$t/$f:$upload_attrib
#/srv/ftp/pub/packages/jw-foss/suse/tumbleweed/rpm/x86_64/jw-pkg-run-1.0.0-74.x86_64.rpm
;;
esac
esac
echo "+ uploading $target"
RSYNC_RSH=$SSH /bin/bash $JWB_SCRIPT_DIR/upload.sh $DIST_PKG_DIR/$f $target
}
upload_pkg()
{
local server
set -e
local p
local v=`read_map $TOPDIR/VERSION | sed 's/-dev//'`
local h=`calculate_hash`
[ -n "$h" ] || fatal "failed to calculate source hash"
case $PKG_FORMAT in
rpm)
server=pkg.janware.com
upload_file $PKG_PROJECT-$v.tar.bz2 tgz
upload_file $PKG_PROJECT-$v.src.rpm src
upload_file $PKG_PROJECT-run-$v.$PKG_ARCH.rpm $PKG_ARCH
upload_file -q $PKG_PROJECT-devel-$v.$PKG_ARCH.rpm $PKG_ARCH
;;
debian|deb)
local -r server=apt.janware.com
local -r distro_subdir=$(platform_info '%{id}/%{codename}')
local conf=`mktemp "/tmp/$myname"_XXXXXX`
cat <<-EOT > $conf
[DEFAULT]
default_host = janware-debian
[janware-debian]
fqdn = $server
# login =
incoming = /var/lib/packager-server/packages/jw-foss/$distro_subdir/incoming/
method = rsync
hash = sha
allow_unsigned_uploads = yes
distributions = debian-8
allowed_distributions = `get_os`
delayed =
run_lintian = no
run_dinstall = no
check_version = yes
passive_ftp = yes
#progress_indicator
scp_compress = yes
ssh_config_options = ForwardAgent=yes,Compression=yes,ServerAliveInterval=30,ConnectTimeout=120
#post_upload_command =
#pre_upload_command =
#default_host_main =
EOT
dput -c $conf janware-debian dist/src/"$PKG_PROJECT"_"$v"_"$PKG_ARCH".changes
rm -f $conf
;;
*)
fatal "Tried to upload with unknown package format \"$PKG_FORMAT\""
;;
esac
write_map $TOPDIR/RELEASES $v
$SCM add $TOPDIR/RELEASES || true
write_map $TOPDIR/HASH $h
$SCM add $TOPDIR/HASH || true
echo "+ scheduling rebuild"
$SSH -l root $server /opt/packager-server/bin/packager-server schedule-rebuild
scm_commit -m "Release $v@`platform`" $TOPDIR/RELEASES $TOPDIR/HASH
if [ "$SCM" = git ]; then
# Don't use extra options, they might contain -l
JW_PKG_SSH_EXTRA_OPTS="" git push || fatal "Failed to push changes to RELEASES and HASH"
fi
}
install_exe_wrapper()
{
local from="`readlink -fm $1`"
local to="$2"
local ext=${from##*.}
local tmp=$to.tmp
case $ext in
py)
cat << EOT | sed 's/^ *|//' > "$tmp"
|#!/usr/bin/python3
|
|import sys
|import subprocess
|args=sys.argv
|args[0] = "$from"
|if subprocess.call([ '/usr/bin/python3' ] + args) != 0:
| print("subprocess failed")
| exit(1)
EOT
;;
pl)
echo -e "#!/bin/bash\n\nexec /usr/bin/perl \"$from\" \"\$@\"" > "$tmp"
#echo -e "#!/bin/bash\n\nexec /usr/bin/perl \"$from\"" > "$tmp"
;;
sh)
echo -e "#!/bin/bash\n\nexec /bin/bash \"$from\" \"\$@\"" > "$tmp"
;;
*)
if file "$from" | grep -qi executable && [[ "$from" =~ "\.so$\|\.so\.[0-9.]*" ]]; then
echo -e "#!/bin/bash\n\nexec \"$from\" \"\$@\"" > "$tmp"
else
ln -sf $from $to
return
fi
;;
esac
chmod 755 "$tmp"
mv "$tmp" $to
}
cmd_build()
{
build_pkg "$@"
}
cmd_upload()
{
upload_pkg
}
check_create_parent()
{
[ "$1" != "true" ] && return 0
local dir=`dirname -z "$2" | xargs -0 readlink -fm`
local path=`readlink -fm "$2"`
if [ "$dir" -a "$dir" != "$path" ]; then
mkdir -p "$dir" || {
echo "failed to create parent dir of \"$1\""
exit 1
}
fi
return 0
}
cmd_log_install()
{
local args="$*"
local c_format=rpm
local c_logfile=""
local c_mode_dir=false
local c_create_leading_dirs=false
local c_group=`id -gn`
local c_owner=`whoami`
local c_suffix=
local c_prefix=
local c_opmode=opmode_install
local c_absolute=0
local c_wrap=0
local c_no_log_dirs=0
local install_opts
set -- `getopt 'DLWi:a:f:l:bg:cdm:o:psS:vAN' $*`
cfgfile_macro()
{
case "$c_format" in
rpm)
if echo "$*" | grep -qe '/etc/\|\.conf$\|\.leases$'; then
echo "%config(noreplace) "
fi
;;
deb|debian)
if echo "$*" | grep -qe '/etc/\|\.conf$\|\.leases$'; then
echo "%config "
fi
;;
*)
;;
esac
}
while [ "$1" != -- ]; do
case $1 in
-f)
c_format=$2
shift;;
-l)
c_logfile=$2
shift;;
-a)
c_use_attr=true
;;
-i)
c_ignore_prefix=$2
shift
;;
-b)
install_opts="$install_opts $1"
;;
-c)
install_opts="$install_opts $1"
;;
-d)
c_mode_dir=true;;
-D)
c_create_leading_dirs=true;;
-g)
c_group=$2
shift;;
-m)
c_mode=$2
shift;;
-o)
c_owner=$2
shift;;
-p)
install_opts="$install_opts $1"
;;
-s)
install_opts="$install_opts $1"
;;
-S)
c_suffix=$2
shift;;
-v)
install_opts="$install_opts $1"
;;
-L)
c_opmode=opmode_link;;
-W)
c_opmode=opmode_link
c_wrap=1;;
-A)
c_absolute=1;;
-N)
c_no_log_dirs=1;;
*)
echo unknown option \"$1\". Exiting. >&2
exit 1;;
esac
shift
done
shift
local args="`echo " $args" | sed -e 's/ -l *[^ ]*//g; s/ -f *[^ ]*//g; s/ -a / /g; s/ -N / /g'`"
if [ -z "$c_use_attr" ]; then
#args="`echo " $args" | sed -e 's/ -g *[^ ]*//g; s/ -m *[^ ]*//g; s/ -o *[^ ]*//g;'`"
args="`echo " $args" | sed -e 's/ -g *[^ ]*//g; s/ -o *[^ ]*//g;'`"
fi
local c_target="`echo $* | awk '{$1=""; print $0}' | sed 's/^ *//'`"
local c_source="`echo $* | awk '{print $1}'`"
case $c_opmode in
opmode_install)
if [ -L "$c_source" ]; then
check_create_parent $c_create_leading_dirs $c_target
cp -d $c_source $c_target || exit $?
else
[ "$c_create_leading_dirs" ] && local install_opts="$install_opts -D"
install $install_opts $args || exit $?
fi
;;
opmode_link)
if [ "$c_mode_dir" = true ]; then
echo "ignoring directory $c_source during link creation"
exit 0
fi
if [ "$c_absolute" != 0 ]; then
c_logfile=""
c_source=`readlink -f $c_source`
else
c_source=`basename $c_source`
fi
check_create_parent $c_create_leading_dirs $c_target
cd `dirname $c_target`
if [ "$c_wrap" = 1 ]; then
install_exe_wrapper $c_source $c_target
else
ln -sf $c_source `basename $c_target`
fi
;;
*)
echo "Mode \"$c_opmode\" not implemented. Exiting." >&2
exit 1
;;
esac
[ "$c_logfile" ] || {
exit 0
}
local file mode installd_file cfgfile dir attr
if [ "$c_mode_dir" = true ]; then
for file in $*; do
[ "$c_no_log_dirs" = 0 ] || continue
mode=$c_mode
[ -L "$file" ] && mode="LINK"
attr=" %attr($mode,$c_owner,$c_group)"
echo "%dir$attr $file" >> $c_logfile
done
else
if [ -f "$c_target" -o -L "$c_target" ]; then
installed_file="$c_target"
cfgfile=""
if [ "$c_mode" ]; then
mode=$c_mode
cfgfile=`cfgfile_macro "$installed_file"`
else
if [ -d "$c_source" ]; then
dir="%dir "
mode=0755
else
cfgfile=`cfgfile_macro "$installed_file"`
dir=""
mode=0644
fi
fi
[ -L "$c_target" ] && mode="LINK"
attr="%attr($mode,$c_owner,$c_group)"
if [ -z "$dir" -o "$c_no_log_dirs" != 0 ]; then
echo "$dir$attr $cfgfile$c_target" | sed "s/^$c_ignore_prefix//" >> $c_logfile
fi
elif [ -d "$c_target" ]; then
for file in $c_source; do
installed_file="$c_target/`basename $file`"
cfgfile=""
if [ "$c_mode" ]; then
mode=$c_mode
cfgfile=`cfgfile_macro "$installed_file"`
else
if [ -d "$file" ]; then
[ "$c_no_log_dirs" = 0 ] || continue
dir="%dir "
mode=0755
else
cfgfile=`cfgfile_macro "$installed_file"`
dir=""
mode=0644
fi
fi
[ -L "$file" ] && mode="LINK"
attr="%attr($mode,$c_owner,$c_group)"
echo "$dir$attr $cfgfile$installed_file" |
sed "s/^$c_ignore_prefix//" >> $c_logfile
done
fi
fi
}
cmd_milk_install_log()
{
milk_install_log_usage()
{
echo "usage: $myname milk-install-log [-h] [-n pkg-name] [-t rpm|deb] [-p remove-prefix] [-s subpackages] install-log output-dir"
[ "$1" ] && exit $1
}
milk_install_log_spec_attr()
{
local attr=$1
shift
#echo "extracting attribute $attr from \"$@\"" >&2
echo "$*" | sed "s/.*attr(\(LINK\|[0-9]\+\),\([^,]\+\),\([^,)]\+\)).*/\\$attr/"
}
cat_log()
{
cat $in | sed '
/\/usr\/bin$/ d
/\/usr\/sbin$/ d
/\/usr\/lib$/ d
/\/usr\/lib64$/ d
/\/usr\/lib\/pkgconfig$/ d
/\/usr\/lib64\/pkgconfig$/ d
' | $user_filter
}
compress()
{
sed ':a;N;$!ba;s/\n//g'
}
make_unique()
{
sed 's/ \+/\n/g' | sort -u | grep .
}
make_alt()
{
make_unique | sed 's/$/$\\|/' | compress
}
local type name prefix in out subpackages
local subpackages="run devel"
local user_filter=cat
eval set -- `getopt -- ht:p:n:s:F: "$@"`
while [ "$1" != -- ]; do
case $1 in
-h)
usage 0;;
-t)
type="$2"; shift;;
-n)
name="$2"; shift;;
-p)
prefix="$2"; shift;;
-s)
subpackages="$2"; shift;;
-F)
user_filter="$2"; shift;;
*)
echo -e "Unexpected argument >$1<\n" >&2
milk_install_log_usage 1;;
esac
shift
done
shift
[ $# != 2 ] && {
echo -e "Too many arguments >$*<\n" >&2
milk_install_log_usage 1
}
local in=$1
local out=$2
local re_hpp_file="[^/]\+\.\(h\|hpp\)$"
local include_dirs=`cat_log | grep "/include/\(.*/\)*$re_hpp_file" | sed "s%.*/include/%/include/%; s%/$re_hpp_file%%"`
include_dirs=`echo /include /include/$name $include_dirs | make_unique`
local include_h_re=`echo $include_dirs | sed 's/ \\+/\\n/g' | sed 's%$%/[^/]\\\\+\\\\.h\\\\(pp\\\\)*%' | make_alt`
local include_dirs_re=`echo $include_dirs | make_alt`
filter_devel="$filter_devel$include_h_re"
filter_devel="$filter_devel$include_dirs_re"
filter_devel="$filter_devel""devel\|make\|/lib[^/]\+\.a$\|/lib[^/]\+\.so$\|/[^/]\+\.exp$\|/[^/]\+\.def$\|/[^/]\+\.lib$\|/[^/]\+\.pc$\|"
filter_devel="$filter_devel/usr/lib[^/]*/pkgconfig"
# TODO: simplify this
case $type in
rpm)
cleanup_line_rpm() {
sed "s% $prefix% %; s/%attr(LINK,[^)]\+)//; s/^\s*//"
}
cat_log | cleanup_line_rpm | grep -ve $filter_devel > $in.$name-run
cat_log | cleanup_line_rpm | grep -e $filter_devel > $in.$name-devel
# TODO: this is unimplemented for debian packages
echo $subpackages | grep -q devel || cat $in.$name-devel >> $in.$name-run
;;
deb)
cleanup_line_deb() {
sed "s|%config\s*||g; s% $prefix% %; s%//*%/%g; s/.*) *//"
}
cat_log | grep -v "%dir" | cleanup_line_deb | grep -ve $filter_devel | sed 's/\(.*\)\/\([^/]\+\) *$/inst-root\1\/\2 \1/' > $out/$name-run.install
cat_log | grep -v "%dir" | cleanup_line_deb | grep -e $filter_devel | sed 's/\(.*\)\/\([^/]\+\) *$/inst-root\1\/\2 \1/' > $out/$name-devel.install
cat_log | grep "%dir" | cleanup_line_deb | grep -ve $filter_devel | sed 's/\(.*\)\/\([^/]\+\) *$/\1\/\2/; s%^/%%' | sort -u > $out/$name-run.dirs
cat_log | grep "%dir" | cleanup_line_deb | grep -e $filter_devel | sed 's/\(.*\)\/\([^/]\+\) *$/\1\/\2/; s%^/%%' | sort -u > $out/$name-devel.dirs
cat_log | grep "%config" | cleanup_line_deb | grep -ve $filter_devel > $out/conffiles.$name-run
cat_log | grep "%config" | cleanup_line_deb | grep -e $filter_devel > $out/conffiles.$name-devel
# Create maintainer scripts
for p in run devel; do
local stage
for stage in pre preun post postun; do
case $stage in
pre) deb_stage=preinst;;
post) deb_stage=postinst;;
preun) deb_stage=prerm;;
postun) deb_stage=postrm;;
esac
local script=$out/$name-$p.$deb_stage
cat <<- EOT > $script
#!/bin/sh
EOT
chmod 755 $script
case $stage in
post)
cat $out/$name-$p.dirs $out/$name-$p.install | grep . | while read file dir; do
#echo read file \"$file\" >&2
file=`echo /$file | sed 's/inst-root\///; s%^//*%/%'`
#echo file is now \"$file\" >&2
#echo grep \"$prefix/*$file$\" $in >&2
# match the end of the log line against
# the file path literally; the line may
# carry a prefix before the path, and a
# regex grep lets dots match other lines
line=`awk -v f="$file" '{ if (substr($0, length($0) - length(f) + 1) == f) print }' $in | head -n 1`
perm=`milk_install_log_spec_attr 1 "$line"`
owner=`milk_install_log_spec_attr 2 "$line"`
group=`milk_install_log_spec_attr 3 "$line"`
echo "chown $owner:$group $file" >> $script
[ "$perm" = "LINK" ] || echo "chmod $perm $file" >> $script
done
;;
*)
;;
esac
echo "== processing stage $stage: cfg_section pkg.$p.$stage" >&2
local os content=""
for os in '' `platform_info '%{cascade}'`; do
local sec=pkg.$p.$stage head=""
if [ "$os" ]; then
sec="$sec.$os"
head="\n# --- $os\n"
fi
cfg_section $sec | grep -q . || continue
content="$content$head`cfg_section $sec`"
done
if [ "$content" ]; then
echo -e "$content" >&2
echo -e "\n$content" >> $script
fi
cat $script | grep -v '^#!/bin\|^$' | grep -q . || rm $script
done
done
;;
*)
milk_install_log_usage 1
;;
esac
}
# ---- here we go
umask 0022
trap goodbye SIGINT
# -- default values
TOPDIR=.
PKG_CHECK_VCS_SYNC_BEFORE_RELEASE=false
myname="${0##*/}"
cmdline="$0 $@"
tmp_mkdef_sh=""
PROJECT_DESCR_FILE=$TOPDIR/make/project.conf
DIST_SRC_DIR=dist/src
DIST_INST_DIR=dist/src
DIST_PKG_DIR=dist/pkg
RPMBUILD_ROOT=""
PKG_PROJECT="$PROJECT"
PKG_REQUIRES_RUN=""
PKG_RECOMMENDS_RUN=""
PKG_REQUIRES_DEVEL=""
PKG_ARCH=$HOSTTYPE
PKG_FORMAT=rpm
SSH=ssh
SCM=cvs
__get_os=""
[ "$RSYNC_RSH" ] && SSH=$RSYNC_RSH
[ "$CVS_RSH" ] && SSH=$CVS_RSH
[ -d .git ] && SCM=git
while [ ${1:0:1} = - ]; do
case "$1" in
-h)
usage 0;;
-t)
eval DIST_SRC_DIR=\"$2\"
shift
;;
-T)
eval RPMBUILD_ROOT=\"$2\"
shift
;;
-p)
eval DIST_PKG_DIR=\"$2\"
shift
;;
-m)
eval JWB_SCRIPT_DIR=\"$2\"
shift
;;
-N)
eval PKG_PROJECT=\"$2\"
shift
;;
-R)
eval PKG_REQUIRES_RUN=\"$2\"
shift
;;
-E)
eval PKG_RECOMMENDS_RUN=\"$2\"
shift
;;
-X)
eval PKG_CONFLICTS_RUN=\"$2\"
shift
;;
-D)
eval PKG_REQUIRES_DEVEL=\"$2\"
shift
;;
-Y)
eval PKG_CONFLICTS_DEVEL=\"$2\"
shift
;;
--provides-run)
eval PKG_PROVIDES_RUN=\"$2\"
shift
;;
--provides-devel)
eval PKG_PROVIDES_DEVEL=\"$2\"
shift
;;
-P)
eval PROJECT=\"$2\"
shift
;;
-a)
eval PKG_ARCH=\"$2\"
shift
;;
-F)
eval PKG_FORMAT=\"$2\"
shift
;;
-B)
eval upload_urlbase=\"$2\"
shift
;;
-A)
eval upload_file_attrib=\"$2\"
shift
;;
*)
echo "unrecognized option $1, giving up" >&2
usage 1
;;
esac
shift
done
[ "$JWB_SCRIPT_DIR" ] || JWB_SCRIPT_DIR="$(dirname $0)"
[ "$PROJECT" ] || PROJECT=`abspath $TOPDIR | xargs basename`
inifile=$PROJECT_DESCR_FILE
. $JWB_SCRIPT_DIR/ini-tools.sh
cmd=$1
shift
export JWB_SCRIPT_DIR=`readlink -f $JWB_SCRIPT_DIR`
export PKG_SH=`readlink -f $0`
# shift
[ ! "$cmd" ] && {
echo "missing command, giving up" >&2
usage 1
}
case $PKG_FORMAT in
rpm)
RPM=/bin/rpm
;;
deb|debian)
RPM="/bin/bash $JWB_SCRIPT_DIR/dpm.sh"
;;
*)
fatal "Unknown package format \"$PKG_FORMAT\""
;;
esac
case $cmd in
check-release)
cmd_check_release
;;
need-release)
if check_release_is_current; then
echo no >&2
exit 1
else
echo yes >&1
exit 0
fi
;;
update-version)
check_update_version "@" || exit 0
;;
version)
cmd_version "$@"
;;
build)
check_cwd
rm -rf ./$DIST_SRC_DIR ./$DIST_PKG_DIR
cmd_build "$@"
;;
release-reinstall)
check_update_version -c "Start version"
cmd_build "$@"
cmd_upload
;;
release)
cd $TOPDIR
check_scm
check_release_is_current -r || {
set -e
check_cwd
rm -rf ./$DIST_SRC_DIR ./$DIST_PKG_DIR
check_update_version || true
cmd_build "$@"
check_pkg_reinstall
cmd_upload
}
;;
upload)
cmd_upload
;;
reinstall)
check_pkg_reinstall
;;
release)
;;
hash)
calculate_hash
;;
log-install)
cmd_log_install "$@"
;;
milk-install-log)
cmd_milk_install_log "$@"
;;
*)
usage 1
;;
esac
goodbye