3e6dbb232f
When separating file names from arguments with --, git log accepts parameters which stand for files which are not under git control (yet). This is necessary in import-foreign-git.sh when new files are getting added to an existing branch.
76 lines
2.6 KiB
Bash
Executable file
76 lines
2.6 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
|
|
(cd $TARGET_DIR && patch -p`expr $SOURCE_LEVELS + 1` <$PATCH)
|
|
# 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
|