hg-mergediff / mktestrepo

#!/bin/sh

# Create a repository with a bunch of merge situations.

IFS="`printf "\n\t"`"
set -eu
cd "`dirname "$0"`"

vcs="${1-hg}"

case "$vcs" in
    hg)
        init() {
            hg init "$1"
        }

        clone() {
            hg clone "$1" "$2"
        }

        add() {
            hg add "$1"
        }

        commit() {
            hg commit -m "$1"
        }

        pull() {
            hg pull "$1"
            hg merge --noninteractive --config "ui.merge=internal:merge" | true
        }

        resolved() {
            hg resolve -m -a
        }
        
        vcsrm() {
            hg remove -f "$1"
        }

        tag() {
            hg tag "$1"
        }

        fixtags() {
            # fix tags after a merge
            grep '^[0-9a-f]' .hgtags > .hgtags2
            mv .hgtags2 .hgtags
        }
    ;;

    git)
        init() {
            mkdir "$1"
            cd "$1"
            git init
            cd ..
        }

        clone() {
            git clone "$1" "$2"
        }

        add() {
            git add "$1"
        }

        commit() {
            git add .
            git commit -m "$1"
        }

        pull() {
            git pull "$1" master | true
        }

        resolved() {
            git add .
        }
        
        vcsrm() {
            git rm -f "$1"
        }

        tag() {
            # note: this is entirely untested
            git tag "$1"
        }

        fixtags() {
            echo "FIXME: git doesn't merge tags yet."
        }
    ;;
esac

wrapping_echo() {
    echo "unchanged line 0"
    echo "unchanged line 1"
    echo "unchanged line 2"
    echo "unchanged line 3"
    echo "unchanged line 4"
    printf "$*\n"
    echo "unchanged line 5"
    echo "unchanged line 6"
    echo "unchanged line 7"
    echo "unchanged line 8"
    echo "unchanged line 9"
}

target="testrepodir/"

[ -d "$target" ] && rm -fr "$target"

mkdir "$target"
cd "$target"

# Create the base
init base
cd base
wrapping_echo "original" > changed_in_merge
add "changed_in_merge"
wrapping_echo "original" > changed_in_one_branch
add "changed_in_one_branch"
wrapping_echo "original" > resolved
add resolved
wrapping_echo "top_bottom" > top_bottom
add top_bottom
echo "bottom line" > adding_line_at_top
add adding_line_at_top
echo "removed_in_merge" > removed_in_merge
add removed_in_merge
commit "Initial."
cd ..

# Create the two clones
for target in a b; do
    clone "base" "$target"
    cd "$target"
    wrapping_echo "in $target" > changed_in_merge
    wrapping_echo "in $target" > resolved
    newfile="only_in_$target"
    echo "$newfile" > "$newfile"
    add "$newfile"
    commit "Adding $newfile"
    cd ..
done

# Make a change which doesn't conflict
cd a
wrapping_echo "nonconflicting change" > "changed_in_one_branch"
commit "Nonconflicting change in 'a'"
cd ..

# Make changes at the top and bottom of a file
cd a
wrapping_echo "middle change" > top_bottom
echo "top change" | cat - top_bottom > tmp
mv tmp top_bottom
commit "Line on the top"
cd ..

cd b
echo "bottom change" >> top_bottom
commit "Line on bottom"
cd ..

# Add tags for easy access
cd a
tag "a"
cd ../b
tag "b"
cd ..

# Create a new repository merging a and b
clone a merged
cd merged
pull ../b
wrapping_echo "merged" > changed_in_merge
wrapping_echo "in a" > resolved
resolved
vcsrm removed_in_merge
echo "added in merge" > added_in_merge
add added_in_merge
echo -e "top line\nbottom line" > adding_line_at_top
fixtags
commit "Merging."
tag "merge"

echo
echo "Dumping you in the merged repository..."
echo "Remember: there are three tags: 'a', 'b' and 'merge'"
echo "For example:"
echo "    hg mergediff -r merge"
echo
"$SHELL"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.