chiark / gitweb /
Merge branch 'master' into refs/top-bases/debian/locations
[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 rname= # Remote branch to base this one on
11
12
13 ## Parse options
14
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;;
23         *)
24                 if [ -z "$name" ]; then
25                         name="$arg"
26                 else
27                         deps="$deps $arg"
28                 fi;;
29         esac
30 done
31
32
33 ## Fast-track creating branches based on remote ones
34
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"
39
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
44 fi
45
46
47 ## Auto-guess dependencies
48
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"
65         fi
66 fi
67
68 [ -n "$merge" -o -n "$restarted" ] || merge="$deps "
69
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"
76
77 # Clean up any stale stuff
78 rm -f "$git_dir/top-name" "$git_dir/top-deps" "$git_dir/top-merge"
79
80
81 ## Create base
82
83 if [ -n "$merge" ]; 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")"
90 fi
91
92
93 ## Merge other dependencies into the base
94
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..."
100
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
110         fi
111 done
112
113
114 ## Set up the topic branch
115
116 git update-ref "refs/top-bases/$name" "HEAD" ""
117 git checkout -b "$name"
118
119 echo "$deps" | sed 's/ /\n/g' >"$root_dir/.topdeps"
120 git add -f "$root_dir/.topdeps"
121
122 author="$(git var GIT_AUTHOR_IDENT)"
123 author_addr="${author%> *}>"
124 {
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>
134
135 Signed-off-by: $author_addr
136 EOT
137 } >"$root_dir/.topmsg"
138 git add -f "$root_dir/.topmsg"
139
140
141
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"