Re: How to maintain packaging files for multiple distributions in the same tree?
On Fri, 16 Feb 2007 07:43:48 +0100, Goswin von Brederlow
<brederlo@informatik.uni-tuebingen.de> said:
> What I want to do is apply a patch to the common ancestry of a set
> of branches but have the RCS system check that it doesn't break any
> branch. Currently I have to apply the patch to one branch and then
> replay, merge, pull, whatever it across all the branches that have
> the same ancestry.
OK. Your problem can be abstracted down to be the same on,
topographically speaking, as the one of having a new upstream version
come out, when you have a whole slew of branches, and have to apply
the upstream change-set to every one of the branches you maintain.
Your specific example can be mapped into this problem, which is,
essentially, changes that have been applied to an ancestor branch
needing to be propagated down every branch, and ensuring that there
are no confilcts.
I have scripted this, so certainly this is easy to do with
arch. In order for the script to make sense to you, you need to
understand a little bit about my working setup. Here is my setup,
which is a fairly common paradigm for me (I started doing this with
cvs-buildpackage):
,----
| $workdir_top/ # contains all the packages
| $pkg/ # (has orig.tar.gz)
| $pkg-$upstream_version/
| debian/
| common/
| upstream/
| $pkg--upstream--$revision
| $pkg--feature-A--$revision
| $pkg--feature-B--$revision
| ....
| $pkg--feature-N--$revision
| $pkg--devo--$revision
`----
The --devo-- branch is the integration branch, which contains
all the features, and is used for building the binary.
Now, suppose there is a new upstream version. I update the
branch $pkg--upstream--$revision using tla_load_dir, but now I have N
feature branches, and the integration branch, to take care of.
Voila. I 'cd $workdir_top/$pkg/upstream', and run the
following script. This script then:
a) Applies the missing changes in the upstream branch to the
integration branch. This is where I get to know if there is going
to be any conflicts in the feature branches. Most of my packages,
most of the time, require no manual intervention. Really. If
there is any manual intervention needed, then, for all conflicts:
i) I inspect the conflict, determine which feature branch would
be affected;
ii) fix the conflict in this throw away integration branch
copy, and satisfy myself the resolution is OK
iii) make the same changes to the affected feature branch.
iv) Commit changes to the feature branch
v) Undo upstream changes to the integration branch, and pull the
changes made to the feature branch. At this point, if we
were to re-try merging the upstream, then this conflict
would be gone.
At this point, I can just re-run the script from the top, and
there will be no conflicts, since all conflicts have been fixed.
b) Applies the missing changes in the upstream branch to all the
feature branches, 1..N.
c) It commits the new revision of the feature branch
d) It does a sync tree in the integration branch, so future merges
are gonna be fine.
e) Finally, it commits the changes in the development branch.
So, for the setup you have with upstream, debian, and ubuntu,
you can generate a very similar shell script to apply common
changes to ancestor branches -- and even generalize it more than I
have needed to.
I really like the scriptability of arch :)
manoj
#!/bin/zsh
# -*- Mode: Sh -*-
# upgrade.sh ---
# Author : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com )
# Created On : Thu Aug 11 13:55:22 2005
# Created On Node : glaurung.internal.golden-gryphon.com
# Last Modified By : Manoj Srivastava
# Last Modified On : Wed Sep 20 11:49:41 2006 (-18000 CDT)
# Last Machine Used: glaurung.internal.golden-gryphon.com
# Update Count : 17
# Status : Unknown, Use with caution!
# HISTORY :
# Description :
#
# arch-tag: 25520dc3-7d73-4b47-ab69-77483e2749d2
#
progname="`basename \"$0\"`"
set -e
workdir_top=/usr/local/src/arch/packages--debian
curdir=$(pwd)
pkg=$(pwd | sed -e 's,^/usr/local/src/arch/packages--debian/,,' -e 's,/.*$,,')
TLA=baz # uses baz status, so do not change
withecho () {
echo " $@" >&2
"$@"
}
action='withecho'
#action='echo'
usageversion () {
cat >&2 <<END
Usage: $progname [options] <package>
Options:
-h print this message
-n "Dry-run" mode - No action taken, only print commands.
-v Make the command verbose
END
}
# parse Command line
# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=$(getopt -a -s bash -o hnv -n 'arch_update' -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-h|--help) usageversion; exit 0 ; shift ;;
-n) action='echo';docmd='NO' ; shift ;;
-v) VERBOSE=1 ; shift ;;
--) shift ; break ;;
*) echo >&2 "Internal error!($i)"
usageversion; exit 1 ;;
esac
done
if [[ -n "$1" ]]; then
pkg=$1
fi
dev=$(${TLA} versions ${pkg}--devo | tail -n 1)
ups=$(${TLA} versions ${pkg}--upstream | tail -n 1)
cd $workdir_top/$pkg/upstream
test -d $dev || echo $dev does not exist
test -d $dev || exit 1
devo_changed=
(set -e; echo "Synchronize the development branch with upstream ($dev)"; cd $dev >/dev/null;
my_missing=$(${TLA} missing $ups)
if [[ -n "$my_missing" ]]; then
for missing in $(${TLA} missing $ups); do
$action ${TLA} replay $missing
devo_changed="YES"
done
fi
echo "The development branch now synched with upstream ($dev)"
echo ''
)
my_branches=$(${TLA} branches $pkg | egrep -v '(devo|upstream)$')
if [[ -n "$my_branches" ]]; then
for branch in $(${TLA} branches $pkg | egrep -v '(devo|upstream)$'); do
my_version=$(${TLA} versions $branch | tail -n 1)
if [[ -n "$my_version" ]]; then
for version in $(${TLA} versions $branch | tail -n 1); do
if [ -d $version ]; then
(set -e; echo "Work on $version"; cd $version>/dev/null;
if ${TLA} lint>/dev/null; then
my_missing=$(${TLA} missing $ups)
if [[ -n "$my_missing" ]]; then
for missing in $(${TLA} missing $ups); do
$action ${TLA} replay $missing
done
$action ${TLA} commit -L 'Synch with upstream'
fi
if ${TLA} status | egrep -v '^(\*|${TLA})' >| /dev/null; then
$action ${TLA} commit -L 'Synch with upstream'
fi
else
echo >&2 $version has untagged files
fi
)
(set -e; echo " Make sure $dev is updated"; cd $dev >/dev/null;
my_missing=$(${TLA} missing $version)
if [[ -n "$my_missing" ]]; then
for missing in $(${TLA} missing $version); do
$action ${TLA} sync-tree $missing
devo_changed="YES"
done
fi
)
echo "Done in $version"
echo ''
fi
done
fi
done
fi
(set -e; cd $dev >/dev/null;
echo "Sync $dev with other branches"
$action ${TLA} commit -L 'Synch with upstream and other branches'
devo_changed=
)
--
Every time I think I know where it's at, they move it.
Manoj Srivastava <srivasta@debian.org> <http://www.debian.org/~srivasta/>
1024D/BF24424C print 4966 F272 D093 B493 410B 924B 21BA DABB BF24 424C
Reply to: