tg.sh: next version is 0.16.1
[topgit/pro.git] / tg-create.sh
blobb2f50e2c55c8cf31b0c934042f60da96da99ebdc
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # (c) Petr Baudis <pasky@suse.cz> 2008
4 # GPLv2
6 deps= # List of dependent branches
7 restarted= # Set to 1 if we are picking up in the middle of base setup
8 merge= # List of branches to be merged; subset of $deps
9 name=
10 rname= # Remote branch to base this one on
13 ## Parse options
15 while [ -n "$1" ]; do
16 arg="$1"; shift
17 case "$arg" in
18 -r)
19 rname="$1"; shift;;
20 -*)
21 echo "Usage: ${tgname:-tg} [...] create [<name> [<dep>...|-r <rname>] ]" >&2
22 exit 1;;
24 if [ -z "$name" ]; then
25 name="$arg"
26 else
27 deps="$deps $arg"
28 fi;;
29 esac
30 done
33 ## Fast-track creating branches based on remote ones
35 if [ -n "$rname" ]; then
36 [ -n "$name" ] || die "no branch name given"
37 ! ref_exists "$name" || die "branch '$name' already exists"
38 has_remote "$rname" || die "no branch $rname in remote $base_remote"
40 if [ -n "$logrefupdates" ]; then
41 mkdir -p "$git_dir/logs/refs/top-bases/$(dirname "$name")" 2>/dev/null || :
42 { >>"$git_dir/logs/refs/top-bases/$name" || :; } 2>/dev/null
44 git update-ref "refs/top-bases/$name" "refs/remotes/$base_remote/top-bases/$rname"
45 git update-ref "refs/heads/$name" "refs/remotes/$base_remote/$rname"
46 info "Topic branch $name based on $base_remote : $rname set up."
47 exit 0
51 ## Auto-guess dependencies
53 deps="${deps# }"
54 if [ -z "$deps" ]; then
55 if [ -z "$name" -a -s "$git_dir/top-name" -a -s "$git_dir/top-deps" -a -s "$git_dir/top-merge" ]; then
56 # We are setting up the base branch now; resume merge!
57 name="$(cat "$git_dir/top-name")"
58 deps="$(cat "$git_dir/top-deps")"
59 merge="$(cat "$git_dir/top-merge")"
60 restarted=1
61 info "Resuming $name setup..."
62 else
63 # The common case
64 [ -z "$name" ] && die "no branch name given"
65 head="$(git symbolic-ref HEAD)"
66 deps="${head#refs/heads/}"
67 [ "$deps" != "$head" ] || die "refusing to auto-depend on non-head ref ($head)"
68 info "Automatically marking dependency on $deps"
72 [ -n "$merge" -o -n "$restarted" ] || merge="$deps "
74 for d in $deps; do
75 ref_exists "$d" ||
76 die "unknown branch dependency '$d'"
77 done
78 ! ref_exists "$name" ||
79 die "branch '$name' already exists"
81 # Clean up any stale stuff
82 rm -f "$git_dir/top-name" "$git_dir/top-deps" "$git_dir/top-merge"
85 ## Find starting commit to create the base
87 if [ -n "$merge" -a -z "$restarted" ]; then
88 # Unshift the first item from the to-merge list
89 branch="${merge%% *}"
90 merge="${merge#* }"
91 info "Creating $name base from $branch..."
92 # We create a detached head so that we can abort this operation
93 git checkout -q "$(git rev-parse "$branch")"
97 ## Merge other dependencies into the base
99 while [ -n "$merge" ]; do
100 # Unshift the first item from the to-merge list
101 branch="${merge%% *}"
102 merge="${merge#* }"
103 info "Merging $name base with $branch..."
105 if ! git merge "$branch"; then
106 info "Please commit merge resolution and call: $tgdisplay create"
107 info "It is also safe to abort this operation using:"
108 info "git$gitcdopt reset --hard some_branch"
109 info "(You are on a detached HEAD now.)"
110 echo "$name" >"$git_dir/top-name"
111 echo "$deps" >"$git_dir/top-deps"
112 echo "$merge" >"$git_dir/top-merge"
113 exit 2
115 done
118 ## Set up the topic branch
120 if [ -n "$logrefupdates" ]; then
121 mkdir -p "$git_dir/logs/refs/top-bases/$(dirname "$name")" 2>/dev/null || :
122 { >>"$git_dir/logs/refs/top-bases/$name" || :; } 2>/dev/null
124 git update-ref "refs/top-bases/$name" "HEAD" ""
125 git checkout -b "$name"
127 echo "$deps" | sed 'y/ /\n/' >"$root_dir/.topdeps"
128 git add -f "$root_dir/.topdeps"
130 author="$(git var GIT_AUTHOR_IDENT)"
131 author_addr="${author%> *}>"
133 echo "From: $author_addr"
134 ! header="$(git config topgit.to)" || echo "To: $header"
135 ! header="$(git config topgit.cc)" || echo "Cc: $header"
136 ! header="$(git config topgit.bcc)" || echo "Bcc: $header"
137 ! subject_prefix="$(git config topgit.subjectprefix)" || subject_prefix="$subject_prefix "
138 echo "Subject: [${subject_prefix}PATCH] $name"
139 echo
140 echo '<patch description>'
141 echo
142 [ "$(git config --bool format.signoff)" = true ] && echo "Signed-off-by: $author_addr"
143 } >"$root_dir/.topmsg"
144 git add -f "$root_dir/.topmsg"
148 info "Topic branch $name set up. Please fill .topmsg now and make initial commit."
149 info "To abort: git$gitcdopt rm -f .top* && git$gitcdopt checkout ${deps%% *} && $tgdisplay delete $name"
151 # vim:noet