2 # TopGit - A different patch queue manager
3 # Copyright (C) 2008 Petr Baudis <pasky@suse.cz>
4 # Copyright (C) 2008 Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
5 # Copyright (C) 2015,2017,2018,2021 Kyle J. McKay <mackyle@gmail.com>
20 Usage: ${tgname:-tg} [...] import [-d <base-branch>] [<option>...] <range>...
21 Or: ${tgname:-tg} [...] import [-d <base-branch>] [<option>...] -s <name> <commit>
23 -p <prefix> prepend <prefix> to branch names (default is 't/')
24 --notes[=<ref>] import notes ref <ref> to .topmsg --- comment
25 --no-notes do not import any notes ref --- comment (default)"
36 branch_prefix
="$1"; shift;;
42 if [ "$val" = "--notes" ]; then
44 notesref
="refs/notes/commits"
45 elif [ -n "$val" ] && [ "${val#-}" = "$val" ]; then
47 refs
/notes
/*) checknref
="$val";;
48 notes
/*) checknref
="refs/$val";;
49 *) checknref
="refs/notes/$val";;
51 git check-ref-format
"$checknref" >/dev
/null
2>&1 ||
52 die
"invalid --notes parameter $arg"
56 die
"invalid --notes parameter $arg"
62 printf '%s\n' "$USAGE" >&2
65 ranges
="$ranges $arg"; rangecnt
=$
(( $rangecnt + 1 ));;
69 [ -z "$single_set" ] ||
[ -z "$branch_prefix_set" ] ||
70 die
"-p does not work with single commit (-s <name> <commit>) mode"
72 if [ -z "$notesflag" ]; then
73 if notesflag
="$(git config --bool --get topgit.notesimport 2>/dev/null)"; then
75 true
) notesflag
=1; notesref
="refs/notes/commits";;
76 false
) notesflag
=0; notesref
=;;
79 notesflag
="$(git config --get topgit.notesimport 2>/dev/null)" &&
83 "-"*) checknref
="$notesflag";;
84 refs
/notes
/*) checknref
="$notesflag";;
85 notes
/*) checknref
="refs/$notesflag";;
86 *) checknref
="refs/notes/$notesflag";;
88 git check-ref-format
"$checknref" >/dev
/null
2>&1 ||
89 die
"invalid topgit.notesImport config setting \"$notesflag\""
97 ensure_ident_available
105 ! header
="$(git config topgit.to)" || headers
="$headers%nTo: $header"
106 ! header
="$(git config topgit.cc)" || headers
="$headers%nCc: $header"
107 ! header
="$(git config topgit.bcc)" || headers
="$headers%nBcc: $header"
108 git
--no-pager log
-1 --pretty=format
:"From: %an <%ae>$headers%nSubject: [PATCH] %s%n%n%b" "$commit"
113 # nice sed script from git-format-patch.sh
116 s/[^-a-z.A-Z_0-9]/-/g
124 git
--no-pager log
-1 --pretty=format
:"%s" "$commit" |
sed -e "$titleScript"
127 origbasedep
="$basedep"
136 info
"---- Importing $commit to $branch_name"
137 lastsymref
="$(git symbolic-ref --quiet HEAD)" ||
:
138 lasthead
="$(git rev-parse --verify --quiet HEAD -- 2>/dev/null)" ||
:
140 if [ -n "$isfirst" ]; then
141 if [ "$basedep" = "" ] ||
[ "$basedep" = "HEAD" ] ||
[ "$basedep" = "@" ]; then
142 if [ -z "$lastsymref" ] ||
[ -z "$lasthead" ]; then
147 tg create
--quiet --no-edit $nodeps "$branch_name" $basedep || die
"tg create failed"
149 get_commit_msg
"$commit" > .topmsg
150 if [ "${notesflag:-0}" = "1" ] && [ -n "$notesref" ]; then
151 notesblob
="$(git notes --ref="$notesref" list "$commit^
0" 2>/dev/null)" ||
:
152 if [ -n "$notesblob" ]; then
153 notesdata
="$(git cat-file blob "$notesblob" 2>/dev/null |
154 git stripspace 2>/dev/null)" ||
:
155 [ -z "$notesdata" ] ||
printf '\n---\n%s\n' "$notesdata" >>.topmsg
158 git add
-f .topmsg .topdeps || die
"git add failed"
159 if [ -n "$tgnosequester" ]; then
160 info
"topgit.sequester is set to false, unadvisedly skipping sequester commit"
162 git commit
-m "tg import create $branch_name" || die
"git commit failed"
164 if ! git cherry-pick
--no-commit "$commit"; then
165 info
"The commit will also finish the import of this patch."
168 git
-c topgit.sequester
=false commit
-C "$commit"
169 info
"++++ Importing $commit finished"
173 if [ -n "$single" ]; then
174 process_commit
$ranges "$single"
178 handle_pick_failure
()
180 # The import got stuck! Let the user fix it up.
181 info
"You are in a subshell."
182 info
"Please commit the cherry-pick resolution and then \`exit\`"
183 info
"If you want to abort the cherry-pick,"
184 info
"use \`exit 1\` to abort the tg import process at this point."
185 info
"Use \`exit 2\` to skip importing this commit and continue."
186 if ! "${SHELL:-@SHELL_PATH@}" -i </dev
/tty
; then
188 if [ $ret -eq 2 ]; then
189 info
"Ok, I will try to continue without importing this commit."
190 if [ -n "$tgnosequester" ]; then
191 git
reset --hard HEAD
193 git
reset --hard HEAD^
195 [ -z "$isfirst" ] || basedep
="$(origbasedep)"
196 [ -z "$lasthead" ] || git update-ref
--no-deref HEAD
"$lasthead"
197 [ -z "$lastsymref" ] || git symbolic-ref HEAD
"$lastsymref"
198 git update-ref
-d "refs/$topbases/$branch_name" ||
:
199 git update-ref
-d "refs/heads/$branch_name" ||
:
200 git
reset --hard HEAD
203 info
"Ok, you aborted the import operation at this point. Now, you just need"
204 info
"to switch back to some sane branch using \`git$gitcdopt checkout\`."
214 info
"Merged already: $comment"
217 if ! process_commit
"$rev" "$branch_prefix$(get_branch_name "$rev")"; then
219 [ -z "$islast" ] ||
return $ret
226 # nice arg verification stolen from git-format-patch.sh
229 for revpair
in $ranges; do
230 rangeidx
=$
(( $rangeidx + 1 ))
233 rev1
="${revpair%..*}"
234 rev2
="${revpair##*..}"
246 cnt
="$(git rev-list --no-walk --count --min-parents=1 --max-parents=1 "$rev2^
0" -- 2>/dev/null)" ||
:
247 if [ "$cnt" = "1" ]; then
248 rev1
="${revpair%^!}^"
250 die
"Not a valid single-parent rev $rev2 ($revpair)"
254 die
"Unknown range spec $revpair"
257 git rev-parse
--verify "$rev1^0" -- >/dev
/null
2>&1 ||
258 die
"Not a valid rev $rev1 ($revpair)"
259 git rev-parse
--verify "$rev2^0" -- >/dev
/null
2>&1 ||
260 die
"Not a valid rev $rev2 ($revpair)"
261 git cherry
-v "$rev1" "$rev2" |
{
262 if read sign
rev comment
; then
263 while read next_sign next_rev next_comment
; do
267 comment
="$next_comment"
269 [ "$rangeidx" != "$rangecnt" ] || islast
=1