1#!/bin/bash
2#
3# git-subtree.sh: split/join git repositories in subdirectories of this one
4#
5# Copyright (c) 2009 Avery Pennarun <apenwarr@gmail.com>
6#
7OPTS_SPEC="\
8git subtree split <revisions> -- <subdir>
9git subtree merge
10
11git subtree does foo and bar!
12--
13h,help show the help
14q quiet
15v verbose
16"
17eval $(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
18. git-sh-setup
19require_work_tree
20
21quiet=
22command=
23
24debug()
25{
26 if [ -z "$quiet" ]; then
27 echo "$@" >&2
28 fi
29}
30
31#echo "Options: $*"
32
33while [ $# -gt 0 ]; do
34 opt="$1"
35 shift
36 case "$opt" in
37 -q) quiet=1 ;;
38 --) break ;;
39 esac
40done
41
42command="$1"
43shift
44case "$command" in
45 split|merge) ;;
46 *) die "Unknown command '$command'" ;;
47esac
48
49revs=$(git rev-parse --default HEAD --revs-only "$@") || exit $?
50dirs="$(git rev-parse --sq --no-revs --no-flags "$@")" || exit $?
51
52#echo "dirs is {$dirs}"
53eval $(echo set -- $dirs)
54if [ "$#" -ne 1 ]; then
55 die "Must provide exactly one subtree dir (got $#)"
56fi
57dir="$1"
58
59debug "command: {$command}"
60debug "quiet: {$quiet}"
61debug "revs: {$revs}"
62debug "dir: {$dir}"
63
64cache_setup()
65{
66 cachedir="$GIT_DIR/subtree-cache/$dir"
67 rm -rf "$cachedir" || die "Can't delete old cachedir: $cachedir"
68 mkdir -p "$cachedir" || die "Can't create new cachedir: $cachedir"
69 debug "Using cachedir: $cachedir" >&2
70 echo "$cachedir"
71}
72
73cache_get()
74{
75 for oldrev in $*; do
76 if [ -r "$cachedir/$oldrev" ]; then
77 read newrev <"$cachedir/$oldrev"
78 echo $newrev
79 fi
80 done
81}
82
83cache_set()
84{
85 oldrev="$1"
86 newrev="$2"
87 if [ -e "$cachedir/$oldrev" ]; then
88 die "cache for $oldrev already exists!"
89 fi
90 echo "$newrev" >"$cachedir/$oldrev"
91}
92
93cmd_split()
94{
95 debug "Splitting $dir..."
96 cache_setup || exit $?
97
98 git rev-list --reverse --parents $revs -- "$dir" |
99 while read rev parents; do
100 newparents=$(cache_get $parents)
101 echo "rev: $rev / $newparents"
102
103 git ls-tree $rev -- "$dir" |
104 while read mode type tree name; do
105 p=""
106 for parent in $newparents; do
107 p="$p -p $parent"
108 done
109 newrev=$(echo synthetic | git commit-tree $tree $p) \
110 || die "Can't create new commit for $rev / $tree"
111 cache_set $rev $newrev
112 done
113 done
114
115 exit 0
116}
117
118cmd_merge()
119{
120 die "merge command not implemented yet"
121}
122
123"cmd_$command"