summaryrefslogtreecommitdiff
path: root/build/import-foreign-git.sh
blob: 61555aa733b8e89c63b16dbd761303a02f7af350 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#! /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