tg.sh: add make_empty_commit function
[topgit/pro.git] / tg-checkout.sh
blob4c3b888a3824dd048b20cbbf8f6afd5548241fb7
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # Copyright (C) 2013 Per Cederqvist <ceder@lysator.liu.se>
4 # Copyright (C) 2015 Kyle J. McKay <mackyle@gmail.com>
5 # All rights reserved.
6 # GPLv2
8 ## Parse options
10 USAGE="Usage: ${tgname:-tg} [...] checkout [ [ push | pop ] [ -a ] | [goto] [--] <pattern> ]"
12 # Subcommands.
13 push=
14 pop=
15 goto=
17 # Options of "push" and "pop".
18 all=
20 # Arguments of "goto".
21 pattern=
23 checkout() {
24 _head="$(git rev-parse --revs-only --abbrev-ref=loose HEAD --)"
25 ref_exists "refs/top-bases/$_head" && branch_annihilated "$_head" && _checkout_opts="-f"
26 git checkout ${_checkout_opts} "$1"
29 while [ $# -gt 0 ]; do
30 arg="$1"
31 shift
33 case "$arg" in
34 -h|--help)
35 printf '%s\n' "$USAGE"
36 exit 0;;
37 -a|--all)
38 all=1;;
39 child|next|push)
40 push=1;;
41 parent|prev|pop|..)
42 pop=1;;
43 goto|--)
44 goto=1
45 [ "$arg" = "--" -o "$1" != "--" ] || shift
46 if [ $# -gt 0 ]; then
47 pattern="$1"
48 shift
49 fi;;
51 if [ -z "$all$push$pop$goto" -a -n "$arg" ]; then
52 goto=1
53 pattern="$arg"
54 else
55 printf '%s\n' "$USAGE" >&2
56 exit 1
57 fi;;
58 esac
59 done
61 if [ "$goto$all" = 11 ]; then
62 die "goto -a does not make sense."
65 if [ -z "$push$pop$goto" ]; then
66 # Default subcommand is "push". This was the most reasonable
67 # opposite of ".." that I could figure out. "goto" would also
68 # make sense as the default command, I suppose.
69 push=1
72 [ "$push$pop$goto" = "1" ] || { err "incompatible options"; printf '%s\n' "$USAGE" >&2; exit 1; }
74 [ -n "$tg_tmp_dir" ] || die "tg-checkout must be run via '$tg checkout'"
75 _depfile="$(mktemp "$tg_tmp_dir/tg-co-deps.XXXXXX")"
76 _altfile="$(mktemp "$tg_tmp_dir/tg-co-alt.XXXXXX")"
78 if [ -n "$goto" ]; then
79 $tg summary -t | grep -e "$pattern" >$_altfile || :
80 no_branch_found="No topic branch matches grep pattern '$pattern'"
81 else
82 branch=`git symbolic-ref -q HEAD` || die "Working on a detached head"
83 branch=`git rev-parse --revs-only --abbrev-ref $branch --`
85 if [ -n "$pop" ]; then
86 no_branch_found="$branch does not depend on any topic"
87 else
88 no_branch_found="No topic depends on $branch"
91 if [ -z "$all" ]; then
92 if [ -n "$pop" ]; then
93 $tg prev -w >$_altfile
94 else
95 $tg next >$_altfile
97 else
98 $tg summary --deps >$_depfile || die "${tgname:-tg} summary failed"
100 if [ -n "$pop" ]; then
101 dir=pop
102 else
103 dir=push
105 script=@sharedir@/leaves.awk
106 awk -f @sharedir@/leaves.awk dir=$dir start=$branch <$_depfile | sort >$_altfile
110 _alts=`wc_l < $_altfile`
111 if [ $_alts = 0 ]; then
112 die "$no_branch_found"
113 elif [ $_alts = 1 ]; then
114 checkout `cat $_altfile`
115 exit $?
118 echo Please select one of the following topic branches:
119 cat -n $_altfile
120 printf '%s' "Input the number: "
121 read n
123 # Check the input
124 sane="$(sed 's/[^0-9]//g' <<-EOT
128 if [ -z "$n" ] || [ "$sane" != "$n" ]; then
129 die "Bad input"
131 if [ $n -lt 1 ] || [ $n -gt $_alts ]; then
132 die "Input out of range"
135 new_branch=`sed -n ${n}p $_altfile`
136 [ -n "$new_branch" ] || die "Bad input"
138 checkout $new_branch