tg-files: simplify arg checking and add sanity check for -i/-w
[topgit.git] / tg-create.sh
blob2edd5379d54c9cc533a0904dafc51b6f566e728c
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: tg [...] create NAME [DEPS...|-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 git update-ref "refs/top-bases/$name" "refs/remotes/$base_remote/top-bases/$rname"
41 git update-ref "refs/heads/$name" "refs/remotes/$base_remote/$rname"
42 info "Topic branch $name based on $base_remote : $rname set up."
43 exit 0
47 ## Auto-guess dependencies
49 deps="${deps# }"
50 if [ -z "$deps" ]; then
51 if [ -z "$name" -a -s "$git_dir/top-name" -a -s "$git_dir/top-deps" -a -s "$git_dir/top-merge" ]; then
52 # We are setting up the base branch now; resume merge!
53 name="$(cat "$git_dir/top-name")"
54 deps="$(cat "$git_dir/top-deps")"
55 merge="$(cat "$git_dir/top-merge")"
56 restarted=1
57 info "Resuming $name setup..."
58 else
59 # The common case
60 [ -z "$name" ] && die "no branch name given"
61 head="$(git symbolic-ref HEAD)"
62 deps="${head#refs/heads/}"
63 [ "$deps" != "$head" ] || die "refusing to auto-depend on non-head ref ($head)"
64 info "Automatically marking dependency on $deps"
68 [ -n "$merge" -o -n "$restarted" ] || merge="$deps "
70 for d in $deps; do
71 ref_exists "$d" ||
72 die "unknown branch dependency '$d'"
73 done
74 ! ref_exists "$name" ||
75 die "branch '$name' already exists"
77 # Clean up any stale stuff
78 rm -f "$git_dir/top-name" "$git_dir/top-deps" "$git_dir/top-merge"
81 ## Find starting commit to create the base
83 if [ -n "$merge" -a -z "$restarted" ]; then
84 # Unshift the first item from the to-merge list
85 branch="${merge%% *}"
86 merge="${merge#* }"
87 info "Creating $name base from $branch..."
88 # We create a detached head so that we can abort this operation
89 git checkout -q "$(git rev-parse "$branch")"
93 ## Merge other dependencies into the base
95 while [ -n "$merge" ]; do
96 # Unshift the first item from the to-merge list
97 branch="${merge%% *}"
98 merge="${merge#* }"
99 info "Merging $name base with $branch..."
101 if ! git merge "$branch"; then
102 info "Please commit merge resolution and call: $tg create"
103 info "It is also safe to abort this operation using:"
104 info "git reset --hard some_branch"
105 info "(You are on a detached HEAD now.)"
106 echo "$name" >"$git_dir/top-name"
107 echo "$deps" >"$git_dir/top-deps"
108 echo "$merge" >"$git_dir/top-merge"
109 exit 2
111 done
114 ## Set up the topic branch
116 git update-ref "refs/top-bases/$name" "HEAD" ""
117 git checkout -b "$name"
119 echo "$deps" | sed 's/ /\n/g' >"$root_dir/.topdeps"
120 git add -f "$root_dir/.topdeps"
122 author="$(git var GIT_AUTHOR_IDENT)"
123 author_addr="${author%> *}>"
125 echo "From: $author_addr"
126 ! header="$(git config topgit.to)" || echo "To: $header"
127 ! header="$(git config topgit.cc)" || echo "Cc: $header"
128 ! header="$(git config topgit.bcc)" || echo "Bcc: $header"
129 ! subject_prefix="$(git config topgit.subjectprefix)" || subject_prefix="$subject_prefix "
130 echo "Subject: [${subject_prefix}PATCH] $name"
131 echo
132 cat <<EOT
133 <patch description>
135 Signed-off-by: $author_addr
137 } >"$root_dir/.topmsg"
138 git add -f "$root_dir/.topmsg"
142 info "Topic branch $name set up. Please fill .topmsg now and make initial commit."
143 info "To abort: git rm -f .top* && git checkout ${deps%% *} && $tg delete $name"
145 # vim:noet