Code

Print out the newly created commitid at the end, for use in other scripts.
[git.git] / git-subtree.sh
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 #
7 OPTS_SPEC="\
8 git subtree split <revisions> -- <subdir>
9 git subtree merge 
11 git subtree does foo and bar!
12 --
13 h,help   show the help
14 q        quiet
15 v        verbose
16 "
17 eval $(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
18 . git-sh-setup
19 require_work_tree
21 quiet=
22 command=
24 debug()
25 {
26         if [ -z "$quiet" ]; then
27                 echo "$@" >&2
28         fi
29 }
31 assert()
32 {
33         if "$@"; then
34                 :
35         else
36                 die "assertion failed: " "$@"
37         fi
38 }
41 #echo "Options: $*"
43 while [ $# -gt 0 ]; do
44         opt="$1"
45         shift
46         case "$opt" in
47                 -q) quiet=1 ;;
48                 --) break ;;
49         esac
50 done
52 command="$1"
53 shift
54 case "$command" in
55         split|merge) ;;
56         *) die "Unknown command '$command'" ;;
57 esac
59 revs=$(git rev-parse --default HEAD --revs-only "$@") || exit $?
60 dirs="$(git rev-parse --sq --no-revs --no-flags "$@")" || exit $?
62 #echo "dirs is {$dirs}"
63 eval $(echo set -- $dirs)
64 if [ "$#" -ne 1 ]; then
65         die "Must provide exactly one subtree dir (got $#)"
66 fi
67 dir="$1"
69 debug "command: {$command}"
70 debug "quiet: {$quiet}"
71 debug "revs: {$revs}"
72 debug "dir: {$dir}"
74 cache_setup()
75 {
76         cachedir="$GIT_DIR/subtree-cache/$$"
77         rm -rf "$cachedir" || die "Can't delete old cachedir: $cachedir"
78         mkdir -p "$cachedir" || die "Can't create new cachedir: $cachedir"
79         debug "Using cachedir: $cachedir" >&2
80 }
82 cache_get()
83 {
84         for oldrev in $*; do
85                 if [ -r "$cachedir/$oldrev" ]; then
86                         read newrev <"$cachedir/$oldrev"
87                         echo $newrev
88                 fi
89         done
90 }
92 cache_set()
93 {
94         oldrev="$1"
95         newrev="$2"
96         if [ "$oldrev" != "latest" -a -e "$cachedir/$oldrev" ]; then
97                 die "cache for $oldrev already exists!"
98         fi
99         echo "$newrev" >"$cachedir/$oldrev"
102 copy_commit()
104         # We're doing to set some environment vars here, so
105         # do it in a subshell to get rid of them safely later
106         git log -1 --pretty=format:'%an%n%ae%n%ad%n%cn%n%ce%n%cd%n%s%n%n%b' "$1" |
107         (
108                 read GIT_AUTHOR_NAME
109                 read GIT_AUTHOR_EMAIL
110                 read GIT_AUTHOR_DATE
111                 read GIT_COMMITTER_NAME
112                 read GIT_COMMITTER_EMAIL
113                 read GIT_COMMITTER_DATE
114                 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
115                 export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
116                 git commit-tree "$2" $3  # reads the rest of stdin
117         ) || die "Can't copy commit $1"
120 cmd_split()
122         debug "Splitting $dir..."
123         cache_setup || exit $?
124         
125         git rev-list --reverse --parents $revs -- "$dir" |
126         while read rev parents; do
127                 newparents=$(cache_get $parents)
128                 debug
129                 debug "Processing commit: $rev / $newparents"
130                 
131                 git ls-tree $rev -- "$dir" |
132                 while read mode type tree name; do
133                         assert [ "$name" = "$dir" ]
134                         debug "  tree is: $tree"
135                         p=""
136                         for parent in $newparents; do
137                                 p="$p -p $parent"
138                         done
139                         
140                         newrev=$(copy_commit $rev $tree "$p") || exit $?
141                         debug "  newrev is: $newrev"
142                         cache_set $rev $newrev
143                         cache_set latest $newrev
144                 done || exit $?
145         done || exit $?
146         latest=$(cache_get latest)
147         if [ -z "$latest" ]; then
148                 die "No new revisions were found"
149         fi
150         echo $latest
151         exit 0
154 cmd_merge()
156         die "merge command not implemented yet"
159 "cmd_$command"