On Fri, 16 Feb 2007 07:43:48 +0100, Goswin von Brederlow
<[EMAIL PROTECTED]> 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 ( [EMAIL PROTECTED] ) 
# 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 <[EMAIL PROTECTED]> <http://www.debian.org/~srivasta/>
1024D/BF24424C print 4966 F272 D093 B493 410B  924B 21BA DABB BF24 424C

Reply via email to