aboutsummaryrefslogtreecommitdiffstats
path: root/tools/kgit-s2q
blob: c63c17a138d1e290e7829b9b5dea1cf820ff66c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
#
# kgit-s2q
#
# Manage a queue of patches described by a series
#
# Based on:
#    - LTSI helper script to generate a git tree from the quilt LTSI tree
#    - git quilt-import
#    - guilt (helper routines)
#
# Copyright 2013-2016 Bruce Ashfield
#
# Licensed under the GPLv2 only.
#
#

usage()
{
cat <<EOF

 kgit-s2q [--author <author name> ] [-n] [--patches <dir>] [-a] [-i] [-f]
          [--commit-sha <type>] [--current] [--series] [--annotated] [--gen] [-c <count>] [-v] [-h] -- [<patch>]"

    --series:     dump the series file and exit
    --gen:        generate patch headers if missing
    --author:     patch author to use if missing, in the format of: "First Last <foo@bar.com>"
    --patches:    directory containing the series file to use
    --current:    show top currently applied patch
    --annotated:  the series is annotated, use the annotations for auto resume
    --fuzzy:      match autoresume on fuzzy heuristics (i.e. subject only)
    --clean:      remove any patch artifacts that may remain from previous runs (i.e. sentinel files)
    --prev:       reset state to the previous patch (retry last patch, failed or not)
    --commit-sha: type of commit sha to create: "author" or "applied". 'author' uses the date of the
                  patch author, and 'applied' uses the date (i.e. current time) of when the patch is applied.
                  The default is 'applied'
    -c:           number of commits to test when autoresuming
    -a:           autoresume series after last sucessfully applied patch
    -i:           interactively prompt if commit information is missing
    -v:           verbose
    -n:           dry run
    -f:           force the first patch of the series as the starting point
    -h:           help

    --:           marks the end of options on the command line

    <patch>:      patch to use as the starting point (turns autoresume off)

EOF
}

silent()
{
	"$@" >/dev/null 2>/dev/null
}

get_branch()
{
	silent git symbolic-ref HEAD || \
		die "Working on a detached HEAD is unsupported."

	git symbolic-ref HEAD | sed -e 's,^refs/heads/,,'
}

next_patch()
{
	COMMIT_START="$1"

	# find the first "real" commit on the branch, i.e. not a merge commit, and not
	# not a commit that came from a merge
	TOP_COMMIT=`git rev-list -n 1 --no-merges --first-parent $COMMIT_START`
	PARENT=`git show $TOP_COMMIT|grep ommit|grep 'pstream\|herry\|tip'|sed 's/.* \([0-9a-f]\+\).*/\1/'`

	CLEN=`echo $PARENT|wc -c`
	if [ $CLEN -eq 41 ] && [ -n "$ANNOTATED_SERIES" ]; then
		# searching via PARENT ID, which is an annotation found in the patch itself
		if [ -z "$FENCE_POST" ]; then
			for i in `tac $DIR/series | grep -v -e ^# -e ^$`; do
				if [ -z "$FENCE_POST" ]; then
					FENCE_POST=`grep -l $PARENT $DIR/$i`
				fi
			done
		fi
	else
		if [ -n "$VERBOSE" ]; then
			echo "[INFO] No annotated resume point (parent ID) falling back to patch id detection"
		fi

		DS1=`mktemp`
		DS2=`mktemp`
		DS3=`mktemp`
		DS4=`mktemp`
		# get the git patch-id of the top commit
		git show $TOP_COMMIT | git patch-id | cut -f1 -d' ' > $DS1

		# and subject
		git format-patch --stdout $TOP_COMMIT~..$TOP_COMMIT  | \
			git mailinfo -b /dev/null /dev/null | grep Subject: | sed 's/Subject: *//' > $DS4

		# find the patch in the series that matches it
		for i in `tac $DIR/series | grep -v -e ^# -e ^$`; do
			git patch-id < $DIR/$i | cut -f1 -d' ' > $DS2
			cmp -s $DS1 $DS2
			if [ $? = 0 ]; then
				FENCE_POST=$i
				break
			fi
		done

		# return if we found a match
		if [ -n "$FENCE_POST" ]; then
			if [ -n "$VERBOSE" ]; then
				echo "[INFO] Matched autoresume via patch ID detection"
			fi
			rm -f $DS1 $DS2 $DS3 $DS4
			return
		fi

		if [ -n "$VERBOSE" ]; then
			echo "[INFO] Could not autodetect resume point via patch ID falling back to diffstat detection"
		fi

		for i in `tac $DIR/series | grep -v -e ^# -e ^$`; do
			cat $DIR/$i | git mailinfo -b /dev/null /dev/null | grep Subject: | sed 's/Subject: *//' > $DS3
			cmp -s $DS3 $DS4
			if [ $? -eq 0 ]; then
				if [ -n "$VERBOSE" ]; then
					echo "[INFO] Found subject match in $i."
				fi
				MAYBE_START=$i
				break
			fi
		done

		# diffstats
		git show $TOP_COMMIT | diffstat -p0 > $DS1
		for i in `tac $DIR/series | grep -v -e ^# -e ^$`; do
			cat $DIR/$i | diffstat -p0 > $DS2
			cmp -s $DS1 $DS2
			if [ $? = 0 ]; then
				# as a second level check, ensure that if diffstats match, subjects
				# should match as well. saves a lot of false positives.
				if [ $i = "$MAYBE_START" ]; then
					FENCE_POST=$i
					if [ -n "$VERBOSE" ]; then
						echo "[INFO] Matched autoresume via diffstat and subject detection" 
					fi
					rm -f $DS1 $DS2 $DS3 $DS4
					return
				fi
			elif [ $i = "$MAYBE_START" ]; then
					FENCE_POST=$i
					# fuzzy match means that we'll let a subject that maches, but not the diffstat
					# be our fencepost. Otherwise, we keep looking.
					if [ -n "$FUZZY_MATCH" ]; then
						if [ -n "$VERBOSE" ]; then
							echo "[WARNING] Subject matched, but diffstat did not. Fuzzy matching for autoresume"
						fi
						rm -f $DS1 $DS2 $DS3 $DS4
						return
					else
						if [ -n "$VERBOSE" ]; then
							echo "[WARNING] Subject matched, but diffstat did not, not autoresuming"
						fi
					fi
			fi
		done

		# if we are here, it means that we couldn't match the top commit to a patch
		# in the series. The search can continue deeper into history, or we can flip
		# the search. Let's take the last entry in the series, and see if its patch-id
		# is on the branch.

		# get the base commit of the branch
		merge_base=`git merge-base HEAD master`
		# dump all of the real commits on the branch from the head commit to the merge base
		# get their patch IDs
		# git rev-list --no-merges --first-parent $merge_base..HEAD | xargs git show | git patch-id  | cut -f1 -d' ' > $DS2
		git rev-list --no-merges $merge_base..HEAD | xargs git show | git patch-id  | cut -f1 -d' ' > $DS2

		# Dump all of the subjects as well
		echo "" > $DS4
		for j in `git rev-list --no-merges $merge_base..HEAD`; do
			git format-patch --stdout $j~..$j  | \
				git mailinfo -b /dev/null /dev/null | grep Subject: | sed 's/Subject: *//' >> $DS4
		done

		for i in `tac $DIR/series | grep -v -e ^# -e ^$`; do
			# grab the patch ID
			cat $DIR/$i | git patch-id | cut -f1 -d' ' > $DS1
		    
			# if our patch ID is in that list, then the series is completely in
			# the branch and is out of sync. Considering warning.
			grep -qF -f $DS1 $DS2
			if [ $? -eq 0 ]; then
				FENCE_POST=$i
				if [ -n "$VERBOSE" ]; then
					echo "[NOTE] series and branch are out of sync"
					echo "[INFO] found the top of series via patch-id in the branch, autoresuming"
					break
				fi
			else
				# we failed to match by patch-id. In case a patch was fuzzed into the tree, double check via
				# subject.
				cat $DIR/$i | git mailinfo -b /dev/null /dev/null | grep Subject: | sed 's/Subject: *//' > $DS3

				grep -qF -f $DS3 $DS4
				if [ $? -eq 0 ]; then
					FENCE_POST=$i
					if [ -n "$VERBOSE" ]; then
						echo "[NOTE] series and branch are out of sync"
						echo "[INFO] found the top of series via subject match in the branch, autoresuming"
					fi
					break
				fi
			fi
		done

		if [ -z "$FENCE_POST" ]; then
			if [ -n "$VERBOSE" ]; then
				echo "[INFO] Could not autodetect resume point via diffstat"
			fi
		else
			if [ -n "$VERBOSE" ]; then
				echo "[INFO] Matched autoresume via diffstat detection"
			fi
		fi

		rm -f $DS1 $DS2 $DS3 $DS4

		return
	fi
}

create_resolution_script()
{
cat <<EOF
#!/bin/bash

  echo "running: git apply --reject .git/rebase-apply/patch"
  git apply --reject .git/rebase-apply/patch > /dev/null
  echo ""
  echo "[INFO] resolving rejects"
  for f in \`git ls-files -o | grep rej | sed 's/\.rej//'\`; do
      echo "[INFO] resolving: \$f"

      rm -f \$f.porig

      echo "   running: wiggle --replace \$f \$f.rej"
      wiggle --replace \$f \$f.rej > /dev/null
      
      echo "[INFO] checking resolution" 
      echo -------------------- original reject -----------------------------
      cat \$f\.rej
      echo --------------------- wiggled in -----------------------------
      diff -up \$f.porig \$f
      echo ------------------------------------------------------------------

      RJSTAT=\`diffstat \$f\.rej |grep changed\`
      echo "Reject  had: "\$RJSTAT

      RFSTAT=\`diff -up \$f.porig \$f | diffstat |grep changed\`
      echo "Refresh has: "\$RFSTAT

      if [ "\$RJSTAT" = "\$RFSTAT" ]; then
          echo -n "Remove porig and reject now? [Y/n/exit] "
          read RESP
          if [ x\$RESP = x -o x\$RESP = xy ] ; then
                rm \$f\.porig \$f\.rej
          elif [ x\$RESP = xexit ] ; then
                 exit 1
          fi
      fi
  done

  git ls-files -m -o -x "meta*" -x "*.rej" -x "*.porig" | xargs git add
  git am --resolved

  echo "[INFO] refresh patch via:"
  echo "  git format-patch -o <original series dir> HEAD^"
EOF
}

AUTORESUME=""
quilt_author=""
commit_sha_type="applied"
while test $# != 0
do
	case "$1" in
	--author)
		shift
		quilt_author="$1"
		;;
	--commit-sha)
                shift
	        commit_sha_type="$1"
	        ;;
	--patches)
		shift
		QUILT_PATCHES="$1"
		;;
	-c)     shift
		DETECT_COUNT="$1"
		;;
	-a)
		AUTORESUME=1
		;;
	-i)
		INTERACTIVE=1
		;;
	-v)
		VERBOSE=1
		;;
	-f)
		FORCE=1
		;;
        --clean)
                CLEAN=1
                ;;
	--prev)
                PREV=1
                ;;
	--gen)
		;;
	--series)
		DUMP_SERIES=1
		;;
	--current)
		DUMP_NEXT_PATCH=1
		;;
	--annotated)
		ANNOTATED_SERIES=1
		;;
        --fuzzy)
		FUZZY_MATCH=1
		;;
	--help|-h)
		usage
		exit
		;;
	--)
		shift
		break
		;;
	esac

	shift
done

# we change directories ourselves
SUBDIRECTORY_OK=1
. "$(git --exec-path)/git-sh-setup"

# if anything is left on the command line, it is a specified starting patch and
# not a fence post
if [ -n "$1" ]; then
	START=$1
	AUTORESUME=
fi


# find the meta directory
get_meta_dir()
{
    # if there's already a located and logged meta directory, just use that and
    # return. Otherwise, we'll look around to see what we can find.
    if [ -f ".metadir" ]; then
        md=`cat .metadir`
        echo $md
        return
    fi

    # determine the meta directory name
    meta_dir_options=`git ls-files -o --directory`
    for m in $meta_dir_options; do
	if [ -d "$m/cfg" ]; then
	    md=`echo $m | sed 's%/%%'`
	fi
    done

    # if nothing was found, we create the minimal structure
    if [ -z "$md" ]; then
        md=".kernel-meta"
    fi

    mkdir -p "${md}/cfg/scratch"

    # store our results where other scripts can quickly find the answer
    echo "${md}" > .metadir
    # return the directory to he caller
    echo $md

    # return the directory to he caller
    echo $md
}

META=`get_meta_dir`
BRANCH=`get_branch`

if [ -n "${CLEAN}" ]; then
    # clean up and then exit
    rm -f $GIT_DIR/kgit-s2q.last
    rm -f $GIT_DIR/kgit-s2q.previous
    exit 0
fi

# for now, this only pops us back to the previous patch, you cannot run it
# twice if you haven't tried to re-apply patches. If we start to track the
# the entire series, or make the .last file "deeper", then we can support
# multiple runs. This is really just a debug assists to restart a patching
# sequence.
if [ -n "${PREV}" ]; then
    if [ -e $GIT_DIR/kgit-s2q.previous ]; then
	cmp -s $GIT_DIR/kgit-s2q.previous $GIT_DIR/kgit-s2q.last
	if [ $? -eq 0 ]; then
	    # previous and last are the same, remove so we restart
	    rm -f $GIT_DIR/kgit-s2q.last
	else
	    # they are different, roll back to previous so we'll
	    # try the same patch again next time around
	    cp -f $GIT_DIR/kgit-s2q.previous $GIT_DIR/kgit-s2q.last
	fi
    else
	rm -f $GIT_DIR/kgit-s2q.last
    fi
    exit 0
fi

# Quilt Author
if [ -n "$quilt_author" ] ; then
	quilt_author_name=$(expr "z$quilt_author" : 'z\(.*[^ ]\) *<.*') &&
	quilt_author_email=$(expr "z$quilt_author" : '.*<\([^>]*\)') &&
	test '' != "$quilt_author_name" &&
	test '' != "$quilt_author_email" ||
	die "malformed --author parameter"
fi

if [ -n "$QUILT_PATCHES" ]; then
	DIR="$QUILT_PATCHES"
else
	DIR="$META/patches/$BRANCH"
fi

if [ ! -d "$DIR" ]; then
	echo ""
	echo "[ERROR] Can't find patch dir at $DIR"
	usage
fi

mkdir -p $META/cfg/scratch || exit 1
REFRESH=$META/cfg/scratch/refresh

SERIES=$DIR/series
if [ ! -f "$SERIES" ]; then
	echo ""
	echo "[ERROR] Can't find series file at $SERIES"
	usage
	exit 1
fi

if [ -n "$DUMP_SERIES" ]; then
	for i in `cat $SERIES`; do
		echo $DIR/$i
	done
	exit 0
fi

if [ -n "$DUMP_NEXT_PATCH" ]; then
	next_patch HEAD

	if [ -z "$FENCE_POST" ] && [ -n "$DETECT_COUNT" ]; then
		count=0
		commit_string="HEAD"
		while [ -z $FENCE_POST ] && [ $count -lt $DETECT_COUNT ]; do
			commit_string=`echo -n $commit_string^`
			count=`expr $count + 1`

			next_patch "$commit_string"
		done
	fi

	if [ -z "$FENCE_POST" ]; then
		cat $SERIES | head -n 1 | sed "s%^%$DIR/%"
	else
		echo "$FENCE_POST"
	fi

	exit 0
fi

diffstat --help > /dev/null 2>&1
if [ $? != 0 ]; then
	echo It appears you dont have diffstat installed.
	echo Please install it.
	exit 1
fi

if [ -n "$AUTORESUME" ] && [ -z "$FENCE_POST" ]; then

	next_patch HEAD

	if [ -z "$FENCE_POST" ] && [ -n "$DETECT_COUNT" ]; then
		count=0
		commit_string="HEAD"
		while [ -z $FENCE_POST ] && [ $count -lt $DETECT_COUNT ]; do
			commit_string=`echo -n $commit_string^`
			count=`expr $count + 1`

			if [ -n "$VERBOSE" ]; then
				echo "[INFO] detection failed, trying previous commit ($commit_string)"
			fi

			next_patch "$commit_string"
		done
	fi
		

	if [ -z "$FENCE_POST" ]; then
		echo "[INFO] Could not autodetect resume point via annotation, patch ID, diffstat or matching filename."
		echo "       Patch that created current HEAD commit $PARENT is unknown. Starting from the first patch."
	else
		echo "[INFO] Resuming from patch after \"$FENCE_POST\""
	fi
fi

# Temporary directories
tmp_dir="$GIT_DIR"/rebase-apply
tmp_msg="$tmp_dir/msg"
tmp_patch="$tmp_dir/patch"
tmp_info="$tmp_dir/info"

COUNT=`cat $SERIES | grep '^[a-zA-Z0-9_]'|wc -l`
APPLIED=0

# Find the intial commit
commit=$(git rev-parse HEAD)

if [ -z "${START}" ]; then
    if  [ -f "$GIT_DIR/kgit-s2q.last" ]; then
        if [ -z "$FORCE" ]; then
            FENCE_POST=`cat $GIT_DIR/kgit-s2q.last`
            echo "[INFO]: fence post found, starting after: ${FENCE_POST}"
        fi
    fi
fi

for i in `cat $SERIES | grep '^[a-zA-Z0-9_/]'`
do
	APPLIED=$[$APPLIED+1]

	# store the last applied patch so we can resume later
	if [ -f $GIT_DIR/kgit-s2q.last ]; then
	    cp -f $GIT_DIR/kgit-s2q.last $GIT_DIR/kgit-s2q.previous
	fi
	# we really should only copy this if the patch PASSES, but this is
	# currently used as a skip type operation, so if we change when this
	# is written, we also need a --skip OR we would need a --retry flag
	# that indicates we should retry failures, versus resuming after them
	# by default.
	echo $i > $GIT_DIR/kgit-s2q.last

	if [ -n "$START" ]; then
		echo $START | grep -qF $i
		if [ $? -ne 0 ]; then
			# if we don't match, skip to the next patch
			continue
		else
			# if we do match, clear our variables so all future patches
			# will be pushed.
			START=""
			FENCE_POST=""
		fi
	else
		if [ -n "$FENCE_POST" ]; then
			# we compare in the series:
			#     links/kernel-cache/ltsi/patches.dma-mapping/...
			# to $FENCE_POST which will have:
			#     meta/patches/standard/base/links/kernel-cache/ltsi/patches.dma-mapping/...
			# so grep for the series sub-path in $FENCE_POST
			echo $FENCE_POST | grep -qF $i
			if [ $? != 0 ]; then
				continue
			else
				FENCE_POST=""
				continue
			fi
		fi
	fi

	if [ ! -f "$DIR/$i" ];then
		echo "[ERROR]: patch $DIR/$i doesn't exist"
		exit 1
	fi

	if [ -n "$VERBOSE" ]; then
		echo "($APPLIED/$COUNT) `basename $i`"
	fi

	git_am_options="--no-verify"
	if [ "$commit_sha_type" == "author" ]; then
		git_am_options="$git_am_options --committer-date-is-author-date"
	fi
	git am $git_am_options --keep-non-patch $DIR/$i > /dev/null 2>&1
	if [ $? != 0 ];then
		git am $git_am_options --abort > /dev/null 2>&1
		echo "[INFO]: check of $DIR/$i with \"git am\" did not pass, trying reduced context."
		git am $git_am_options -C1 --keep-non-patch $DIR/$i > /dev/null 2>&1
		if [ $? = 0 ]; then
			commit=$(git rev-parse HEAD)
			echo $DIR/$i $commit >> $REFRESH
			continue
		fi
		git am $git_am_options --abort > /dev/null 2>&1
		echo "[INFO]: Context reduced git-am of $DIR/$i with \"git am\" did not work, trying \"apply\"."
	else
		commit=$(git rev-parse HEAD)
		continue
	fi

	# git am failed; take manual processing path.
	if [ ! -d "$tmp_dir" ]; then
		mkdir $tmp_dir || exit 2
	fi

	git mailinfo -b "$tmp_msg" "$tmp_patch" \
	    <"$DIR/$i" >"$tmp_info" || exit 3
	test -s "$tmp_patch" || {
		echo "Patch is empty.  Was it split wrong?"
		exit 1
	}

	#  Parse the author information
	GIT_AUTHOR_NAME=$(sed -ne 's/Author: //p' "$tmp_info")
	GIT_AUTHOR_EMAIL=$(sed -ne 's/Email: //p' "$tmp_info")
	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
	while test -z "$GIT_AUTHOR_EMAIL" && test -z "$GIT_AUTHOR_NAME" ; do
		if [ -n "$quilt_author" ] ; then
			GIT_AUTHOR_NAME="$quilt_author_name";
			GIT_AUTHOR_EMAIL="$quilt_author_email";
		else
			if [ -z "$INTERACTIVE" ]; then
				GIT_AUTHOR_NAME="invalid_git config"
				GIT_AUTHOR_EMAIL="<unknown@unknown>"
			else
				echo "No author found in $patch_name" >&2;
				echo "---"
				cat $tmp_msg
				printf "Author: ";
				read patch_author

				echo "$patch_author"

				patch_author_name=$(expr "z$patch_author" : 'z\(.*[^ ]\) *<.*') &&
				patch_author_email=$(expr "z$patch_author" : '.*<\([^>]*\)') &&
				test '' != "$patch_author_name" &&
				test '' != "$patch_author_email" &&
				GIT_AUTHOR_NAME="$patch_author_name" &&
				GIT_AUTHOR_EMAIL="$patch_author_email"
			fi
		fi
	done
	GIT_AUTHOR_DATE=$(sed -ne 's/Date: //p' "$tmp_info")
	SUBJECT=$(sed -ne 's/Subject: //p' "$tmp_info")
	export GIT_AUTHOR_DATE SUBJECT
	if [ -z "$SUBJECT" ] ; then
		SUBJECT=$(echo $patch_name | sed -e 's/.patch$//')
	fi

	# update-ref is what "git am" does.
	git update-ref ORIG_HEAD HEAD
	git apply --index -C1 "$tmp_patch"
	if [ $? != 0 ]; then

	        # put all the pieces that git am requires to complete
	        # the resolution of the reject. Why not just use git am ?
	        # The reason we are in here is because the patch was likely
	        # missing some requirement elements for git am to apply it.
	        # so rather that re-writing the patch (Which could be in a
	        # read only location), we generate what we need and put 
	        # the parts in place, so it can be resolved and not happen
	        # again.
		echo 1 > $tmp_dir/last
		echo 1 > $tmp_dir/next
		echo t > $tmp_dir/utf8

		echo "GIT_AUTHOR_NAME='$GIT_AUTHOR_NAME'"   > $tmp_dir/author-script
		echo "GIT_AUTHOR_EMAIL='$GIT_AUTHOR_EMAIL'" >> $tmp_dir/author-script
		echo "GIT_AUTHOR_DATE='$GIT_AUTHOR_DATE'"  >> $tmp_dir/author-script

		# also copied from git-am.sh
		git rev-parse --verify -q HEAD > $tmp_dir/abort-safety

		touch $tmp_dir/keep
		touch $tmp_dir/scissors
		touch $tmp_dir/no_inbody_headers
		touch $tmp_dir/quiet
		touch $tmp_dir/threeway
		touch $tmp_dir/applying
		touch $tmp_dir/apply-opt
		touch $tmp_dir/sign

		cp $DIR/$i $tmp_dir/0001

		echo "$SUBJECT"  > $tmp_dir/final-commit
		echo >> $tmp_dir/final-commit
		cat "$tmp_msg" >> $tmp_dir/final-commit

		create_resolution_script > $tmp_dir/resolve_rejects
		chmod +x $tmp_dir/resolve_rejects

		echo "[ERROR]: Application of $DIR/$i failed."
		echo "         Patch needs to be refreshed. Sample resolution script:"
		echo "             .git/rebase-apply/resolve_rejects"
		exit 1
	else
		# git apply worked, take next steps.
		tree=$(git write-tree) &&
		commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git commit-tree $tree -p $commit) &&
		git update-ref -m "kgit-s2q: $patch_name" HEAD $commit || exit 4

		# also set the ORIG_HEAD, since it is used before applying patches
	        git update-ref ORIG_HEAD HEAD

		echo $DIR/$i $commit >> $REFRESH

		GIT_AUTHOR_NAME=""
		GIT_AUTHOR_EMAIL=""
		GIT_AUTHOR_DATE=""
		SUBJECT=""
	fi
done

# if we've failed to locate $FENCE_POST in the series, and
# not subsequently cleared $FENCE_POST, then something evil
# has happened, and we'll do nothing and silently
# return zero which otherwise would be nasty.
if [ -n "$FENCE_POST" ]; then
	echo Failed to locate $FENCE_POST in the series
	exit 1
fi