openbsd-ports/x11/kde4/kde-release-helper
2013-05-09 18:33:50 +00:00

679 lines
15 KiB
Bash

#!/bin/ksh
set -e
MY_NAME=$(basename "$0")
MY_NAME="${MY_NAME:-kde-release-helper}"
usage() {
cat >&2 <<EOF
usage: $MY_NAME prepare new-KDE-version
$MY_NAME check-lists
$MY_NAME deps
$MY_NAME merge
$MY_NAME next
$MY_NAME new port-name [commentary ...]
$MY_NAME run
$MY_NAME show {built|packaged|status|unpackaged} [all|l10n|sc]
$MY_NAME update status
typical usecases:
$MY_NAME prepare 4.9.3
cd ../kde493
# start hacking
$MY_NAME check-lists
$MY_NAME new kdepkg some cool KDE stuff
$MY_NAME deps
$MY_NAME run
# after some progress but before committing
$MY_NAME update status
# when new KDE release is ready
$MY_NAME merge
EOF
exit 1
}
# echo-and-run
ear() {
echo "$*" >&2
"$@"
}
CLEANUP_ITEMS=
cleanup() {
test -n "$CLEANUP_ITEMS" && ear rm -Rf $CLEANUP_ITEMS
}
trap cleanup EXIT
# Files to ignore during prepare and megre stages in addition to git ones
IGNORE_FILES="*.port.mk $MY_NAME STATUS"
# File containing list of KDE packages in order they should be built
DEPS_LIST=kde.deps.list
# List of options for diff(1) to make it ignore files above
diff_ignore_opts() {
for F in ${IGNORE_FILES}; do
echo -n " -x $F"
done
}
# Arg: KDE version in X.Y.Z format
# Output: kdeXYZ
kde_port_dir() {
if ! echo "$1" | egrep -q '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "$1 is not a valid KDE version (X.Y.Z)" >&2
exit 1
fi
echo "kde$1" | sed -e 's/\.//g'
}
# List all ports (subdirectories) in current directory.
# Assume we're in KDE ports root directory.
# Output does not include l10n, see list_l10n_ports() below.
list_local_ports() {
ls | while read P; do
# Test for being directory for safety in case of symlinks
test X"$P" != Xl10n -a \
X"$P" != Xtemplate -a \
-d "$P" \
-a -e "$P"/Makefile || continue
echo "$P"
done
}
# Assume we're in KDE ports root directory.
# Input: list of subdirectories.
# Output: list of distribution names.
port_dir_to_distname() {
while read D; do
(cd $D && make show=DISTNAME)
done | sed -Ee 's@-([0-9]|\$).*@@' | sort
}
# Assume we're in KDE ports root directory.
list_l10n_ports() {
test -d l10n || return 0
for L in $(cd l10n/ru && make show=ALL_LANGS); do
echo "kde-l10n-${L}"
done | sort
}
# Assume we're in KDE ports root directory.
list_l10n_ports_dirs() {
test -d l10n || return 0
for L in $(cd l10n/ru && make show=ALL_LANGS); do
echo "l10n/$L"
done | sort
}
# Assume we're in the apporiate port's directory
list_remote_source() {
local LIST URL
local V=`make show=MODKDE4_VERSION`
for URL in $(make MASTER_SITE_BACKUP= show=MASTER_SITES); do
echo "$URL" | grep -q '^ftp://' || continue
LIST="$(ear curl -sl $URL |
sed -e s@-${V}.*@@ |
grep -v '^\.' |
sort)" || continue
test `echo -n "$LIST" | wc -l` -gt 1 || continue
echo "$LIST"
return 0
done
echo "Could not retrieve source files list." >&2
echo "Probably more FTP servers with NLIST command supported" >&2
echo "are needed in MASTER_SITES." >&2
return 1
}
# Assume the same as list_remote_source().
# Input: sorted local list of ports.
# Output: list of new ports prefixed with "+"
compare_sources_lists() {
T="`mktemp -t srccomp.XXXXXXXX`"
OCLEANUP_ITEMS="$CLEANUP_ITEMS"
CLEANUP_ITEMS="$CLEANUP_ITEMS $T"
list_remote_source >"$T"
test -s "$T" && diff -u - "$T" || true
rm "$T"
CLEANUP_ITEMS="$OCLEANUP_ITEMS"
}
# Assume we're in KDE ports root directory.
kde_version() {
(cd libs && make show=MODKDE4_VERSION)
}
# Arguments: port, status
print_status_line() {
printf '%-32s%s\n' "$1" "$2"
}
is_started() {
test -d "`cd $1 && make show=WRKSRC`"
}
is_configured() {
test -e "`cd $1 && make show=_CONFIGURE_COOKIE`"
}
is_built() {
test -e "`cd $1 && make show=_BUILD_COOKIE`"
}
is_tested() {
test -e "`cd $1 && make show=_TEST_COOKIE`"
}
is_packaged() {
local P F FOUND FLAVORS=`cd $1 && make show=FLAVORS`
for P in `cd $1 && make show=BUILD_PACKAGES`; do
FOUND=
for F in "" ${FLAVORS}; do
if [ -e "`cd $1 && SUBPACKAGE=$P FLAVOR=$F make show=PKGFILE`" ]; then
FOUND=Y
break
fi
done
test -n "$FOUND" || return 1
done
return 0
}
is_locked() {
# LOCKDIR could be empty, see ports(7)
LOCKDIR="${LOCKDIR:-X`cd $1 && make show=LOCKDIR`}"
if [ "$LOCKDIR" != X ]; then
test -e "${LOCKDIR#X}/`cd $1 && make show=FULLPKGNAME`.lock"
else
# XXX Better detection mechanizm?
false
fi
}
# Argument: KDE version in X.Y.Z format.
is_stable_ver() {
# KDE alpha/beta/etc. versions start from 80
test 80 -gt `echo $1 | sed -E 's/^.*\.([0-9]+)$/\1/'`
}
expand_port_list() {
case ${1:-all} in
all)
list_local_ports
list_l10n_ports_dirs
;;
sc)
list_local_ports
;;
l10n)
list_l10n_ports_dirs
;;
*)
usage
;;
esac
}
### Main actions go here
prepare() {
test $# -eq 1 || usage
if ! [ -f ../kde4/kde4.port.mk -a X"`cd .. && basename $(pwd)`" = Xx11 ]; then
echo "Please run $MY_NAME from KDE 4 directory in ports tree" >&2
exit 2
fi
local NEW_KDE_PORT_VER=$1; shift
local CUR_KDE_PORT_VER=`kde_version`
cd ..
local NEW_KDE_PORT_DIR=`kde_port_dir "$NEW_KDE_PORT_VER"`
if [ -e $NEW_KDE_PORT_DIR ]; then
echo "x11/$NEW_KDE_PORT_DIR already exists" >&2
exit 2
fi
echo '==> copying ports directory' >&2
CLEANUP_ITEMS="$CLEANUP_ITEMS $NEW_KDE_PORT_DIR"
cp -R "$OLDPWD" $NEW_KDE_PORT_DIR
local LOCAL_PORTS=`cd $NEW_KDE_PORT_DIR && list_local_ports`
echo '==> removing extra files' >&2
for F in $IGNORE_FILES; do ear rm -f $NEW_KDE_PORT_DIR/$F; done
find $NEW_KDE_PORT_DIR -name 'PLIST*.orig' -print0 | xargs -0rt rm
if is_stable_ver $NEW_KDE_PORT_VER; then
if is_stable_ver $CUR_KDE_PORT_VER; then
# just mark distinfo missing
ear rm -f $NEW_KDE_PORT_DIR/l10n/distinfo
else
# need to copy l10n back from some stable directory
ear mkdir -p $NEW_KDE_PORT_DIR/l10n
ear cp -R kde4/l10n/* $NEW_KDE_PORT_DIR/l10n
fi
else
# Unstable KDE versions usually lacks l10n.
# And if not, we don't care either, they will not
# hit the CVS anyway.
ear rm -Rf $NEW_KDE_PORT_DIR/l10n
fi
for P in $LOCAL_PORTS; do
ear rm -f $NEW_KDE_PORT_DIR/$P/distinfo
done
echo '==> removing REVISION marks' >&2
for P in $LOCAL_PORTS; do
local OCLEANUP_ITEMS="$CLEANUP_ITEMS"
CLEANUP_ITEMS="$CLEANUP_ITEMS $NEW_KDE_PORT_DIR/$P/Makefile.orig"
perl -ni.orig -e '/^REVISION/ or print' $NEW_KDE_PORT_DIR/$P/Makefile
cmp -s $NEW_KDE_PORT_DIR/$P/Makefile{.orig,} || echo $P
rm $NEW_KDE_PORT_DIR/$P/Makefile.orig
CLEANUP_ITEMS="$OCLEANUP_ITEMS"
done
echo '==> patching Makefile.inc' >&2
local MI=$NEW_KDE_PORT_DIR/Makefile.inc
local T=`mktemp -u "$MI".XXXXXXXXXXX`
OCLEANUP_ITEMS="$CLEANUP_ITEMS"
CLEANUP_ITEMS="$CLEANUP_ITEMS $T"
local MSPATCH OSTABLE=1 NSTABLE=1
is_stable_ver $CUR_KDE_PORT_VER || OSTABLE=0
is_stable_ver $NEW_KDE_PORT_VER || NSTABLE=0
if [[ $OSTABLE -eq $NSTABLE ]]; then
MSPATCH=cat
elif [[ $OSTABLE -eq 0 ]]; then
MSPATCH="sed /MASTER_SITES/s@unstable/@stable/@"
else
MSPATCH="sed /MASTER_SITES/s@stable/@unstable/@"
fi
awk "
/^MODKDE4_FLAVOR[[:space:]]*:?=/ {
print \"MODKDE4_FLAVOR = ${NEW_KDE_PORT_DIR}\";
VL = 1;
}
{
if (VL) {
VL = 0;
} else {
print;
}
}
" <"$MI" | $MSPATCH >"$T"
if ! grep -q ^MODKDE4_FLAVOR "$T"; then
# MODKDE4_FLAVOR could be missing
echo >>"$T"
echo "MODKDE4_FLAVOR = $NEW_KDE_PORT_DIR" >>"$T"
fi
mv "$T" "$MI"
if ! is_stable_ver $NEW_KDE_PORT_VER; then
echo '==> patching Makefile' >&2
sed -Ee '/^SUBDIR[[:space:]]*\+=[[:space:]]*l10n/d' \
<$NEW_KDE_PORT_DIR/Makefile >"$T"
mv "$T" $NEW_KDE_PORT_DIR/Makefile
fi
CLEANUP_ITEMS="$OCLEANUP_ITEMS"
echo "==> creating STATUS" >&2
for P in $LOCAL_PORTS `list_l10n_ports_dirs`; do
print_status_line $P WAITING \
>>${NEW_KDE_PORT_DIR}/STATUS
done
# Avoid removing newly created directory
CLEANUP_ITEMS=
}
check_lists() {
test $# -eq 0 || usage
echo '==> checking for new source packages' >&2
list_local_ports |
port_dir_to_distname |
(cd libs && compare_sources_lists) |
egrep '^[\+-][^\+-]' |
grep -v '^+kde-l10n' || true
test -d l10n || return 0
echo '==> checking for l10n package list changes' >&2
list_l10n_ports |
(cd l10n/ru && compare_sources_lists) |
egrep '^[\+-][^\+-]' || true
}
build_deps_list() {
test $# -eq 0 || usage
local KDEDIR=$(kde_port_dir `kde_version`)
local P BDEPS DEP DEP2 T
T=$(mktemp ${DEPS_LIST}.XXXXXXXX)
OCLEANUP_ITEMS="$CLEANUP_ITEMS"
CLEANUP_ITEMS="$CLEANUP_ITEMS $T"
echo "===> Gathering lists of KDE ports packaged or being built" >&2
for P in `list_local_ports; list_l10n_ports_dirs`; do
# normalize build dependencies list by removing all but pkgpath
BDEPS=$(cd $P && make show="BUILD_DEPENDS LIB_DEPENDS" |
sed -Ee 's@[^[:space:]]+:@@g')
# take care of KDE SC dependencies only
for DEP2 in $BDEPS; do
echo "$DEP2"
done |
fgrep "x11/${KDEDIR}/" |
sed -e "s%x11/${KDEDIR}/%%" -e "s%\$% ${P}%"
done >"$T"
mv "$T" "$DEPS_LIST"
CLEANUP_ITEMS="$OCLEANUP_ITEMS"
}
choose_next() {
test $# -eq 0 || usage
local P
tsort <"$DEPS_LIST" | while read P; do
is_packaged $P && continue
is_locked $P && continue
if is_built $P; then
echo "# $P was built"
echo "(cd $P && make update-plist) && \\"
echo "(cd $P && make port-lib-depends-check) && \\"
echo "(cd $P && make package)"
elif is_configured $P; then
echo "# $P was configured"
echo "(cd $P && make build)"
elif is_started $P; then
echo "# $P was started"
echo "(cd $P && make configure)"
else
echo "# $P was not started"
echo "(cd $P && make patch)"
fi
break
done
}
new_port() {
test $# -ge 1 || usage
NEW_P=$1; shift
mkdir "$NEW_P" "$NEW_P"/pkg
sed -e "s@XYZ@${NEW_P}@g" \
-e "s@^COMMENT.*@COMMENT = $*@" \
<template/Makefile \
>"$NEW_P"/Makefile
echo "Now run:" >&2
echo "cd $NEW_P && ${VISUAL:-${EDITOR:-vi}} Makefile" >&2
}
merge_back() {
test $# -eq 0 || usage
# Avoid erroring out here, we'll print a nicer message below.
local SKDEV=`cd libs && make show=_MODKDE4_STABLE || true`
local KDEV=`cd libs && make show=MODKDE4_VERSION || true`
if [ -f kde4.port.mk -o X"`cd .. && basename $(pwd)`" != Xx11 -o \
X"$KDEV" = X ]; then
echo "Please run $MY_NAME from directory with KDE4 ports being tested" >&2
exit 2
fi
local SKPD=kde4
local KPD=$(kde_port_dir $KDEV)
cd ..
T=`mktemp -t kdepatch.XXXXXXXX`
CLEANUP_ITEMS="$CLEANUP_ITEMS $T"
SKVERLINE="`egrep -n ^_MODKDE4_STABLE ${SKPD}/kde4.port.mk | head -1`"
cat >$T <<EOF
Here is a summary patch to be applied, please review. Note that STATUS files
are missing in the diff to make it smaller, they will be handled automatically.
If you proceed and NOT abort, commit message editor will appear, two times:
* First time for merging new directory into x11/kde4;
* Second time for removing old directory.
To abort, just press ^C and then quit pager.
And do not worry, it's distributed VCS and you always can go back. Because you
have already commited all your work, didn't you?
--- ${SKPD}/kde4.port.mk
+++ ${SKPD}/kde4.port.mk
@@ -${SKVERLINE%%:*},1 +${SKVERLINE%%:*},1 @@
-${SKVERLINE#*:}
+_MODKDE4_STABLE = ${KDEV}
EOF
diff -urNp -I '^MODKDE4_FLAVOR[[:space:]]*=' -X ../.gitignore \
`diff_ignore_opts` $SKPD $KPD \
| sed -e "s@^+++ ${KPD}/@+++ ${SKPD}/@" >>$T
${PAGER:-more} <$T
patch -C -E -p0 <$T
patch -E -p0 <$T
rm $T
rm $SKPD/STATUS
mv $KPD/STATUS $SKPD/
git add $SKPD
git commit -m "Merge KDE $KDEV from testing directory." -e -- $SKPD
rm -R $KPD
git commit -m "Remove KDE $KDEV testing directory." -e -- $KPD
}
run_job() {
test $# -eq 0 || usage
for P in `list_local_ports`; do
if is_packaged $P || is_locked $P; then
continue
fi
echo "==> Working on port $P" >&2
if is_built $P; then
local TARGETS=
if ! ls $P/pkg/PLIST*.orig >/dev/null 2>&1; then
TARGETS=update-plist
fi
TARGETS="$TARGETS port-lib-depends-check package"
TARGETS="$TARGETS lib-depends-check install clean"
(cd $P && make $TARGETS)
elif is_configured $P; then
(cd $P && make build)
elif is_started $P; then
(cd $P && make configure)
else
(cd $P && make makesum prepare)
fi
done
}
# Assume to be running in KDE4 ports directory
show_status() {
local P T V PORTLIST=$(expand_port_list "$1")
V="`kde_version`"
for P in $PORTLIST; do
if is_packaged $P; then
print_status_line $P PACKAGED
elif is_built $P; then
print_status_line $P BUILT
elif is_configured $P; then
print_status_line $P CONFIGURED
elif is_started $P; then
print_status_line $P STARTED
else
print_status_line $P WAITING
fi
done
}
show() {
test $# -ge 1 -a $# -le 2 || usage
if ! [ -f ../kde4/kde4.port.mk -a \
X"`cd .. && basename $(pwd)`" = Xx11 ]; then
echo "Please run $MY_NAME from a KDE 4 directory in ports tree" >&2
exit 2
fi
local P WHAT PORTLIST=$(expand_port_list "$2")
WHAT=$1; shift
case $WHAT in
c|co|con|conf|confi|config|configu|configur|configure|configured)
for P in $PORTLIST; do
is_configured $P && echo $P
done
;;
b|bu|bui|buil|built)
for P in $PORTLIST; do
is_built $P && echo $P
done
;;
p|pa|pac|pack|packa|packag|package|packaged)
for P in $PORTLIST; do
is_packaged $P && echo $P
done
;;
s|st|sta|stat|statu|status)
show_status "$@"
;;
u|un|unp|unpa|unpac|unpack|unpacka|unpackag|unpackage|unpackaged)
for P in $PORTLIST; do
is_packaged $P || echo $P
done
;;
*)
usage
esac
true
}
update_status() {
test $# -eq 0 || usage
local V=`kde_version`
local T="`mktemp -u STATUS.XXXXXXXX`"
local OCLEANUP_ITEMS="$CLEANUP_ITEMS"
CLEANUP_ITEMS="$T $CLEANUP_ITEMS"
if [ -e "STATUS" ]; then
echo "===> Updating status of KDE $V porting"
local P S
show_status all | awk "
BEGIN {
while (getline L <\"STATUS\") {
split(L, PARTS);
STATUS[PARTS[1]] = PARTS[2];
}
# From most to least useful, the latest one isn't actually needed now.
STATUSES[1] = \"PACKAGED\";
STATUSES[2] = \"BUILT\";
STATUSES[3] = \"CONFIGURED\";
STATUSES[4] = \"STARTED\";
#STATUSES[5] = \"WAITING\";
# We cannot use 'for(... in STATUSES)' because it doesn't restart
# on every loop, but starts cycling items from the position where
# previous loop was interrupted.
NSTATUSES = 4
}
/^([[:space:]]*#.*)?\$/ {
next;
}
{
for (I = 1; I < NSTATUSES; I++) {
S = STATUSES[I];
if (STATUS[\$1] == S || \$2 == S) {
printf(\"%-32s%s\\n\", \$1, S);
next;
}
}
printf(\"%-32s%s\\n\", \$1, \"WAITING\");
}
" | tee "$T"
else
echo "===> Old status file missing, recreating"
show_status "$WHAT" | tee "$T"
fi
mv "$T" "STATUS"
CLEANUP_ITEMS="$OCLEANUP_ITEMS"
}
update() {
test $# -ge 1 || usage
if ! [ -f ../kde4/kde4.port.mk -a \
X"`cd .. && basename $(pwd)`" = Xx11 ]; then
echo "Please run $MY_NAME from a KDE 4 directory in ports tree" >&2
exit 2
fi
local CMD=$1; shift
case $CMD in
s|st|sta|stat|statu|status)
update_status "$@"
;;
*)
usage
;;
esac
}
# All actions take (at least) one argument
test $# -ge 1 || usage
ACTION=$1; shift
case $ACTION in
p|pr|pre|prep|prepa|prepar|prepare)
prepare "$@"
;;
check-l|check-li|check-lis|check-list|check-lists)
check_lists "$@"
;;
d|de|dep|deps)
build_deps_list "$@"
;;
m|me|mer|merg|merge)
merge_back "$@"
;;
nex|next)
choose_next "$@"
;;
new)
new_port "$@"
;;
r|ru|run)
run_job "$@"
;;
s|sh|sho|show)
show "$@"
;;
u|up|upd|upda|updat|update)
update "$@"
;;
esac