#!/bin/bash
#
# FIXME: This script has some GITisms. They stem from missing Cogito
# features, such as exporting patches to mbox format, applying patches
# from e-mail, merging multiple tags at once, verifying signed tags and
# repacking the repository.
#
# Not that there would be anything wrong per se with this; GIT and Cogito
# can interoperate fine (except few quite special situations; see the README
# for details) and you can mix the commands; Cogito might never provide
# wrappers for some of the GIT features which are nevertheless awesomely
# useful, like `git bisect`.
# This function is appended as "&& should_fail" to commands which should
# fail. Readers please pretend that it is not here at all - it is useful
# for executing this script to make sure we did not break it with any
# Cogito changes.
should_fail () {
echo "Expected failure, got success on line ${BASH_LINENO[0]}" \
"- aborting" >&2
trap - exit
exit 1
}
# Conversely, if something fails when it shouldn't, report it and exit.
set -e
trap 'echo >&2 "Unexpected error $? on line $LINENO"; exit 1' exit
### Set up playground
sh 0000-playground.sh
TOP=$(pwd)
ALICE=$TOP/Playground/Alice
BOB=$TOP/Playground/Bob
CHARLIE=$TOP/Playground/Charlie
cd Playground
### Alice's first version
cd $ALICE
tar xf $TOP/0001-alice.tar
cd rpn
# Being a tidy girl, she places it under Cogito
echo "Alice's first version" | cg-init
cg-tag -d "First ever version of RPN" rpn-0.1
# Alice decides on OSL-2.1
cd $ALICE/rpn
cp $TOP/0002-alice-license.txt osl-2.1.txt
# The new file has to be added
cg-add osl-2.1.txt
# Fix up the files
patch -p1 -i $TOP/0003-alice-osl.patch
# Now save all, and tag it for later reference
cg-commit -m "Place under OSL-2.1"
cg-tag -d "Place under OSL-2.1" rpn-0.2
# Alice creates a public repository for the new toy
cg-admin-setuprepo $ALICE/rpn.git
cg-branch-add public "$ALICE/rpn.git" # Shortcut for the public repository
# Alice pushes her master _and_ the two tags to the public repository
cg-push public -t rpn-0.1 -t rpn-0.2
### Bob hears about this exciting new program, gets a copy from Alice
cd $BOB
cg-clone $ALICE/rpn.git
cd rpn
# Bob thinks the declarations for the stack should go in a header file
cp $TOP/0004-bob-stack_h stack.h
patch -p1 -i $TOP/0005-bob-stack_h.patch
cg-add stack.h
cg-commit -m "Place stack declarations in header file" \
-m "Create stack.h, move declarations of stack manipulation into it" \
-m "Include stack.h in rpn.c and stack.h"
# Later, he remembers he didn't fix the Makefile
patch -p1 -i $TOP/0006-bob-Makefile.patch
cg-commit -m "Update dependencies for stack.h in Makefile"
### Alice has been busy too...
cd $ALICE/rpn
# She adds the 'd'rop operation
patch -p1 -i $TOP/0007-alice-drop.patch
cg-commit -m "Add drop command" \
-m "Change rpn.c to add handling for 'd'rop"
# Then she adds 'C'lear, and a first stab at documentation
patch -p1 -i $TOP/0008-alice-clear.patch
cp $TOP/0009-alice-README.txt README
cg-add README
cg-commit -m "Add clear stack command" \
-m "Change rpn.c to add handling for 'C'lear" \
-m "Add README file with fist stab at documentation"
# The result works fine, so she prepares to release it
cg-tag -d "First public release" rpn-0.3
cg-push public -t rpn-0.3
cg-export ../rpn-0.3.tar.bz2
### Bob tells Alice of his changes, Alice prepares to get them.
cd $ALICE/rpn
cg-switch -r master bob
cg-status -g
# Alice needs to register his remote branch
cg-branch-add bobswork $BOB/rpn
# Now try to merge Bob's work to the bob branch
cg-update bobswork && should_fail
# There are conflicts in rpn.c. Looking at the file, Alice sees the
# difference between her version and Bob's:
#: ...
#: <<<<<<< bob
#: extern double pop(void);
#: extern void push(double);
#: extern void clear(void);
#:
#: =======
#: >>>>>>> bobswork
#: extern int getsym(void);
#: ...
# Alice keeps Bob's version
ed rpn.c < $TOP/0010-alice-bob-fixup.ed
# cg-commit after resolving conflicts from failed merge will autogenerate
# the commit message.
cg-commit </dev/null
# She fixes up Makefile and stack.h a bit
patch -p1 -i $TOP/0011-alice-cleanup.patch
cg-commit -m "Fix Makefile and stack.h"
## Charlie heard of RPN, and wants to hack too.
cd $CHARLIE
cg-clone $ALICE/rpn.git rpn
cd rpn
# He hacks around, and messes up rpn.c. To restore the saved version:
rm rpn.c
cg-restore rpn.c
# Finally, he has the changes he wants
cp $TOP/0012-charlie-lexer_h lexer.h
patch -p1 -i $TOP/0013-charlie-lexer.patch
cg-add lexer.h
cg-commit -m "Add proper header file for lexer" \
-m "Create lexer.h, move lexer declarations into it." \
-m "Include lexer.h in rpn.c and lexer.c" \
-m "Update dependencies in Makefile"
# Charlie emails the patch to Alice:
# cg-mkpatch -d .. -r rpn-0.3..master
git format-patch -o .. --mbox --signoff -r rpn-0.3
# Only git can create mbox formatted output
# Compare the result to 0014-charlie-email
### Alice is busy meanwhile...
cd $ALICE/rpn
cg-switch master
patch -p1 -i $TOP/0015-alice-mod.patch
cg-commit -m "Add mod operator" \
-m "Add handling for '%' (fmod(3)) in rpn.c"
patch -p1 -i $TOP/0016-alice-dup.patch
cg-commit -m "Add duplication operator" \
-m "Add handling for 'D'up in rpn.c"
# Alice publishes her work-in-progress
cg-push public
### Alice gets Charlie's fix, creates a new branch for his changes
cd $ALICE/rpn
cg-switch -r rpn-0.3 charlie
cg-status -g
# Check what's inside the patch. There is no Cogito equivalent yet.
git apply --stat $TOP/0014-charlie-email
git apply --summary $TOP/0014-charlie-email
git apply --check $TOP/0014-charlie-email
# Everything looks OK
git applymbox $TOP/0014-charlie-email
# This doesn't work well yet
# cg-patch < $TOP/0014-charlie-email
### Alice integrates the changes in the branches for the next release
cd $ALICE/rpn
cg-switch master
# Alice tries "git merge" instead of "cg-merge" since she wanted to
# merge both branches at once, which "cg-merge" cannot do.
git merge "Integrate changes from Bob and Charlie" master bob charlie \
&& should_fail
# Automatic 3-way merge fails! Have to do it step by step
cg-reset
cg-merge bob && should_fail
# Merge fails:
#: ...
#: <<<<<<< master
#: $(CC) $(CFLAGS) $^ -lm -o $@
#: =======
#: $(CC) $(CFLAGS) $^ -o $@
#:
#: rpn.o: stack.h
#: stack.o: stack.h
#: lexer.o:
#: >>>>>>> bob
ed Makefile < $TOP/0017-alice-bob-fixup.ed
cg-commit -m "Integrate Bob's changes"
cg-merge charlie && should_fail
# Merge conflicts!
#: ...
#: <<<<<<< master
#: $(CC) $(CFLAGS) $^ -lm -o $@
#:
#: rpn.o: stack.h
#: stack.o: stack.h
#: lexer.o:
#: =======
#: $(CC) $(CFLAGS) $^ -o $@
#:
#: rpn.o lexer.o: lexer.h
#:
#: >>>>>>> charlie
ed Makefile < $TOP/0018-alice-charlie-fixup1.ed
#: ...
#: <<<<<<< master
#: extern int getsym(void);
#:
#: =======
#: extern double pop(void);
#: extern void push(double);
#: extern void clear(void);
#:
#: >>>>>> charlie
#: ...
ed rpn.c < $TOP/0019-alice-charlie-fixup2.ed
cg-commit -m "Integrate Charlie's changes"
# Give proper credits
cp $TOP/0020-alice-CONTRIBUTORS.txt CONTRIBUTORS
cg-add CONTRIBUTORS
cg-commit -m "Add CONTRIBUTORS"
# Wrong file name...
cg-mv CONTRIBUTORS CREDITS
cg-commit -m "Rename CONTRIBUTORS to CREDITS"
# Pack it so it uses less space
git repack
git prune-packed
# Second public release
cg-tag -d "New public release" rpn-0.4
cg-push public -t rpn-0.4
cg-export ../rpn-0.4.tar.bz2
# Also pack public repository
GIT_DIR=$ALICE/rpn.git git repack
GIT_DIR=$ALICE/rpn.git git prune-packed
### Bob updates his version to Alice's
cd $BOB/rpn
cg-fetch
# Bob has doubts about the latest version...
# (Note that originally, rpn-0.4 was signed, but that would require you
# to set up a GPG key before running the script... verify-tag on unsigned
# scripts does not make much sense.)
git verify-tag rpn-0.4 && should_fail
# Everything's OK, integrate the changes
cg-merge
# Great, we are done.
trap - exit
echo "Script completed successfully!"
syntax highlighted by Code2HTML, v. 0.9.1