syncevolution/build/import-foreign-git.sh
Patrick Ohly 36dd42a030 import-foreign-git.sh: added interactive patch fixing
If patch fails, let caller resolve it manually before continuing. Can
happen if the imported history includes branches and merges with merge
conflicts.
2011-08-30 10:31:20 +02:00

84 lines
2.8 KiB
Bash
Executable file

#! /bin/sh
#
# Run this inside the top level of a clean
# syncevolution git repository with the following
# parameters:
# - file system path for foreign git repository
# - name of local branch for importing changes
# - a local directory into which the source file(s) is to be placed,
# preserving all remaining directories after stripping
# - number of directory levels to strip from source file(s)
# - one or more source file names, with paths relative to the
# foreign repository
set -e
set -x
FOREIGN="$1"
shift
TARGET_BRANCH="$1"
shift
TARGET_DIR="$1"
shift
SOURCE_LEVELS="$1"
shift
SOURCE="$@"
FOREIGN_NAME=`basename $FOREIGN`
TARGET=`for i in $SOURCE; do echo $i | perl -p -e "s;([^/]*/){$SOURCE_LEVELS};$TARGET_DIR/;"; done`
PATCH=`mktemp`
MSG=`mktemp`
git checkout $TARGET_BRANCH
# find lastest imported commit:
# import everything unless one of the files already exists,
# in which case we assume that all of the others also exist
revisions=master
for i in $TARGET; do
if [ -f $i ]; then
revisions="`git log -n 1 -- $TARGET | tail -1`..master"
break
fi
done
count=`(cd "$FOREIGN" && git log -p $revisions -- $SOURCE) | grep '^commit' | wc -l`
# iterate over all commits from oldest to newest
i=1
while [ $i -le $count ]; do
# get complete patch
(cd "$FOREIGN" && git log -p --max-count=1 --skip=`expr $count - $i` $revisions -- $SOURCE) >$PATCH
# get just the commit message
(cd "$FOREIGN" && git log --max-count=1 --skip=`expr $count - $i` $revisions -- $SOURCE) >$MSG
# apply patch to file: enter directory and skip pathname from patch
if ! (cd $TARGET_DIR && patch -p`expr $SOURCE_LEVELS + 1` <$PATCH); then
echo "patch failed in $TARGET_DIR: patch -p`expr $SOURCE_LEVELS + 1` <$PATCH"
echo "continue? yes/no [no]"
read yesno
if [ "$yesno" != "yes" ]; then
exit 1
fi
fi
# now commit it (can't use commit because we want to preserve date):
# - add to index
for t in $TARGET; do
[ -f $t ] && git add $t
done
# - write index
id=`git write-tree`
# - find information for commit and commit
parent=`git show-ref --heads --hash $TARGET_BRANCH`
origid=`grep ^commit $MSG | sed -e 's/commit //'`
GIT_AUTHOR_NAME="`grep ^Author: $MSG | sed -e 's/Author: \(.*\) <.*/\1/'`"
GIT_AUTHOR_EMAIL="`grep ^Author: $MSG | sed -e 's/Author: [^<]*<\([^>]*\)>/\1/'`"
GIT_AUTHOR_DATE="`grep ^Date: $MSG | sed -e 's/Date: *//'`"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
id=`(grep '^ ' $MSG | sed -e 's/^ *//' && echo && echo "$FOREIGN_NAME commit ID:" && echo $origid) | git commit-tree $id -p $parent`
# - update branch and check it out
git update-ref refs/heads/$TARGET_BRANCH $id
git reset --hard $TARGET_BRANCH
# next patch
i=`expr $i + 1`
done