tg-contains.sh: new command to show containing TopGit branch(es)
[topgit/pro.git] / tg-checkout.sh
blob44d53bdab2edac246959ec7321fbf484904587fc
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 [--iow] [-f] [ [ 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 iowoptval=
24 forceval=
25 checkout() {
26 _head="$(git rev-parse --revs-only --abbrev-ref=loose HEAD --)"
27 ref_exists "refs/$topbases/$_head" && branch_annihilated "$_head" && _checkout_opts="-f"
28 git checkout $iowoptval $forceval ${_checkout_opts} "$1"
31 usage() {
32 printf '%s\n' "$USAGE" >&2
33 exit 1
36 while [ $# -gt 0 ]; do
37 arg="$1"
38 shift
40 case "$arg" in
41 -h|--help)
42 printf '%s\n' "$USAGE"
43 exit 0;;
44 -a|--all)
45 all=1;;
46 --ignore-other-worktrees|--iow)
47 iowoptval="$iowopt";;
48 --force|-f)
49 forceval=-f;;
50 child|next|push)
51 push=1;;
52 parent|prev|pop|..)
53 pop=1;;
54 goto|--)
55 if [ -n "$goto" ]; then
56 if [ -n "$pattern" ]; then
57 usage
58 else
59 pattern="$1"
60 continue
63 goto=1
64 [ "$arg" = "--" -o "$1" != "--" ] || shift
65 if [ $# -gt 0 ]; then
66 pattern="$1"
67 shift
68 fi;;
69 -?*)
70 if [ -z "$goto" ]; then
71 usage
73 pattern="$arg";;
75 if [ -z "$all$push$pop$goto" -a -n "$arg" ]; then
76 goto=1
77 pattern="$arg"
78 else
79 usage
80 fi;;
81 esac
82 done
84 if [ "$goto$all" = 11 ]; then
85 die "goto -a does not make sense."
88 if [ -z "$push$pop$goto" ]; then
89 # Default subcommand is "push". This was the most reasonable
90 # opposite of ".." that I could figure out. "goto" would also
91 # make sense as the default command, I suppose.
92 push=1
95 [ "$push$pop$goto" = "1" ] || { err "incompatible options"; usage; }
97 [ -n "$tg_tmp_dir" ] || die "tg-checkout must be run via '$tg checkout'"
98 _depfile="$(mktemp "$tg_tmp_dir/tg-co-deps.XXXXXX")"
99 _altfile="$(mktemp "$tg_tmp_dir/tg-co-alt.XXXXXX")"
101 if [ -n "$goto" ]; then
102 $tg summary -t | grep -e "$pattern" >"$_altfile" || :
103 no_branch_found="No topic branch matches grep pattern '$pattern'"
104 else
105 branch="$(git symbolic-ref -q HEAD)" || die "Working on a detached head"
106 branch="$(git rev-parse --revs-only --abbrev-ref "$branch" --)"
108 if [ -n "$pop" ]; then
109 no_branch_found="$branch does not depend on any topic"
110 else
111 no_branch_found="No topic depends on $branch"
114 if [ -z "$all" ]; then
115 if [ -n "$pop" ]; then
116 $tg prev -w >"$_altfile"
117 else
118 $tg next >"$_altfile"
120 else
121 $tg summary --deps >$_depfile || die "${tgname:-tg} summary failed"
123 if [ -n "$pop" ]; then
124 dir=pop
125 else
126 dir=push
128 script=@sharedir@/leaves.awk
129 awk -f @sharedir@/leaves.awk dir=$dir start=$branch <$_depfile | sort >"$_altfile"
133 _alts=$(( $(wc -l <"$_altfile") ))
134 if [ $_alts = 0 ]; then
135 die "$no_branch_found"
136 elif [ $_alts = 1 ]; then
137 checkout "$(cat "$_altfile")"
138 exit $?
141 catn() {
142 sed = | paste -d ":" - - | sed 's/^/ /;s/^ *\(......\):/\1 /'
145 echo Please select one of the following topic branches:
146 catn <"$_altfile"
147 printf '%s' "Input the number: "
148 read -r n
150 # Check the input
151 sane="$(sed 's/[^0-9]//g' <<-EOT
155 if [ -z "$n" ] || [ "$sane" != "$n" ]; then
156 die "Bad input"
158 if [ $n -lt 1 ] || [ $n -gt $_alts ]; then
159 die "Input out of range"
162 new_branch="$(sed -n ${n}p "$_altfile")"
163 [ -n "$new_branch" ] || die "Bad input"
165 checkout "$new_branch"