tg: avoid passing '--' options terminator to git cat-file
[topgit/pro.git] / tg-push.sh
blob276cc449c5d62c0f3ad62ab4b1b5962e145eb4e2
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # GPLv2
5 ## Parse options
7 recurse_deps=1
8 tgish_deps_only=
9 dry_run=
10 force=
11 push_all=
12 outofdateok=
13 branches=
14 remote=
15 signedopt=
16 atomicopt=
17 opt4=
18 opt6=
20 while [ -n "$1" ]; do
21 arg="$1"; shift
22 case "$arg" in
23 --no-deps)
24 recurse_deps=;;
25 --dry-run)
26 dry_run=--dry-run;;
27 -f|--force)
28 force=--force;;
29 --signed|--signed=*)
30 signedopt="$arg";;
31 --atomic)
32 atomicopt="$arg";;
33 -4|--ipv4)
34 opt4="$arg";;
35 -6|--ipv6)
36 opt6="$arg";;
37 --tgish-only)
38 tgish_deps_only=1;;
39 -a|--all)
40 push_all=1;;
41 --allow-outdated)
42 outofdateok=1;;
43 -h|--help)
44 echo "Usage: ${tgname:-tg} [...] push [--dry-run] [--force] [--no-deps] [--tgish-only] [-r <pushRemote>] [-a | --all | <branch>...]"
45 exit 0;;
46 -r)
47 remote="$1"
48 shift
51 v_strip_ref arg "$arg"
52 branches="${branches:+$branches }$arg";;
53 esac
54 done
55 [ -z "$push_all" ] || [ -z "$branches" ] || die "branch names not allowed with --all"
57 [ -n "$remote" ] || remote="$(git config topgit.pushremote 2>/dev/null)" || :
58 [ -n "$remote" ] || remote="$base_remote"
60 if [ -z "$remote" ]; then
61 warn "either use -r <pushRemote> argument or set topgit.[push]remote"
62 die "no push remote location given"
65 [ -n "$branches$push_all" ] || branches="HEAD"
66 if [ -n "$push_all" ]; then
67 branches="$(non_annihilated_branches | paste -s -d " " -)"
68 else
69 oldbranches="$branches"
70 branches=
71 while read name && [ -n "$name" ]; do
72 if [ "$name" = "HEAD" ] || [ "$name" = "@" ]; then
73 sr="$(git symbolic-ref --quiet HEAD)" || :
74 [ -n "$sr" ] || die "cannot push a detached HEAD"
75 case "$sr" in refs/heads/*);;*)
76 die "HEAD is a symref to other than refs/heads/..."
77 esac
78 ref_exists "$sr" || die "HEAD ($sr) is unborn"
79 b="${sr#refs/heads/}"
80 else
81 ref_exists "refs/heads/$name" || die "no such ref: refs/heads/$name"
82 b="$name"
84 case " $branches " in *" $b "*);;*)
85 branches="${branches:+$branches }$b"
86 esac
87 done <<-EOT
88 $(sed 'y/ /\n/' <<-LIST
89 $oldbranches
90 LIST
92 EOT
93 unset oldbranches
96 _listfile="$(get_temp tg-push-listfile)"
98 push_branch()
100 # FIXME should we abort on missing dependency?
101 [ -z "$_dep_missing" ] || return 0
103 # if so desired omit non tgish deps
104 [ -z "$tgish_deps_only" ] || [ -n "$_dep_is_tgish" ] || return 0
106 # filter out plain SHA1s. These don't need to be pushed explicitly as
107 # the patches that depend on the sha1 have it already in their ancestry.
108 ! is_sha1 "$_dep" || return 0
110 echol "refs/heads/$_dep" >> "$_listfile"
111 [ -z "$_dep_is_tgish" ] ||
112 echo "refs/$topbases/$_dep" >> "$_listfile"
115 if [ -z "$outofdateok" ]; then
116 needs_update_check_clear
117 needs_update_check $branches
118 if [ -n "$needs_update_behind" ]; then
119 printf 'branch not up-to-date: %s\n' $needs_update_behind >&2
120 die "all branches to be pushed must be up-to-date (try --allow-outdated)"
124 no_remotes=1
125 while read name && [ -n "$name" ]; do
126 # current branch
127 # re-use push_branch, which expects some pre-defined variables
128 _dep="$name"
129 _dep_is_tgish=1
130 _dep_missing=
131 ref_exists "refs/$topbases/$_dep" ||
132 _dep_is_tgish=
133 push_branch "$name"
135 # deps but only if branch is tgish
136 [ -z "$recurse_deps" ] || [ -z "$_dep_is_tgish" ] ||
137 recurse_deps push_branch "$name"
138 done <<EOT
139 $(sed 'y/ /\n/' <<LIST
140 $branches
141 LIST
145 [ -s "$_listfile" ] || die "nothing to push"
147 # remove multiple occurrences of the same branch
148 sort -u "$_listfile" |
149 sed 's,[^A-Za-z0-9/_.+-],\\&,g' |
150 xargs git push $opt4 $opt6 $dry_run $force $atomicopt $signedopt "$remote"