chiark / gitweb /
Factor out rev-parse --verify calls to new ref_exists() function
[topgit.git] / tg-create.sh
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # (c) Petr Baudis <pasky@suse.cz>  2008
4 # GPLv2
5
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
11
12 ## Parse options
13
14 while [ -n "$1" ]; do
15         arg="$1"; shift
16         case "$arg" in
17         -*)
18                 echo "Usage: tg create NAME [DEPS...]" >&2
19                 exit 1;;
20         *)
21                 if [ -z "$name" ]; then
22                         name="$arg"
23                 else
24                         deps="$deps $arg"
25                 fi;;
26         esac
27 done
28
29
30 ## Auto-guess dependencies
31
32 deps="${deps# }"
33 if [ -z "$deps" ]; then
34         if [ -z "$name" -a -s "$git_dir/top-name" -a -s "$git_dir/top-deps" -a -s "$git_dir/top-merge" ]; then
35                 # We are setting up the base branch now; resume merge!
36                 name="$(cat "$git_dir/top-name")"
37                 deps="$(cat "$git_dir/top-deps")"
38                 merge="$(cat "$git_dir/top-merge")"
39                 restarted=1
40                 info "Resuming $name setup..."
41         else
42                 # The common case
43                 [ -z "$name" ] && die "no branch name given"
44                 head="$(git symbolic-ref HEAD)"
45                 deps="${head#refs/heads/}"
46                 [ "$deps" != "$head" ] || die "refusing to auto-depend on non-head ref ($head)"
47                 info "Automatically marking dependency on $deps"
48         fi
49 fi
50
51 [ -n "$merge" -o -n "$restarted" ] || merge="$deps "
52
53 for d in $deps; do
54         ref_exists "$d"  ||
55                 die "unknown branch dependency '$d'"
56 done
57 ! ref_exists "$name"  ||
58         die "branch '$name' already exists"
59
60 # Clean up any stale stuff
61 rm -f "$git_dir/top-name" "$git_dir/top-deps" "$git_dir/top-merge"
62
63
64 ## Create base
65
66 if [ -n "$merge" ]; then
67         # Unshift the first item from the to-merge list
68         branch="${merge%% *}"
69         merge="${merge#* }"
70         info "Creating $name base from $branch..."
71         # We create a detached head so that we can abort this operation
72         git checkout -q "$(git rev-parse "$branch")"
73 fi
74
75
76 ## Merge other dependencies into the base
77
78 while [ -n "$merge" ]; do
79         # Unshift the first item from the to-merge list
80         branch="${merge%% *}"
81         merge="${merge#* }"
82         info "Merging $name base with $branch..."
83
84         if ! git merge "$branch"; then
85                 info "Please commit merge resolution and call: tg create"
86                 info "It is also safe to abort this operation using:"
87                 info "git reset --hard some_branch"
88                 info "(You are on a detached HEAD now.)"
89                 echo "$name" >"$git_dir/top-name"
90                 echo "$deps" >"$git_dir/top-deps"
91                 echo "$merge" >"$git_dir/top-merge"
92                 exit 2
93         fi
94 done
95
96
97 ## Set up the topic branch
98
99 git update-ref "refs/top-bases/$name" "HEAD" ""
100 git checkout -b "$name"
101
102 echo "$deps" | sed 's/ /\n/g' >"$root_dir/.topdeps"
103 git add -f "$root_dir/.topdeps"
104
105 author="$(git var GIT_AUTHOR_IDENT)"
106 author_addr="${author%> *}>"
107 {
108         echo "From: $author_addr"
109         ! header="$(git config topgit.to)" || echo "To: $header"
110         ! header="$(git config topgit.cc)" || echo "Cc: $header"
111         ! header="$(git config topgit.bcc)" || echo "Bcc: $header"
112         ! subject_prefix="$(git config topgit.subjectprefix)" || subject_prefix="$subject_prefix "
113         echo "Subject: [${subject_prefix}PATCH] $name"
114         echo
115         cat <<EOT
116 <patch description>
117
118 Signed-off-by: $author_addr
119 EOT
120 } >"$root_dir/.topmsg"
121 git add -f "$root_dir/.topmsg"
122
123
124
125 info "Topic branch $name set up. Please fill .topmsg now and make initial commit."
126 info "To abort: git rm -f .top* && git checkout ${deps%% *} && tg delete $name"