@@ -231,12 +231,14 @@ cache_miss () {
231
231
}
232
232
233
233
check_parents () {
234
- missed=$( cache_miss " $@ " )
234
+ missed=$( cache_miss " $1 " )
235
+ local indent=$(( $2 + 1 ))
235
236
for miss in $missed
236
237
do
237
238
if ! test -r " $cachedir /notree/$miss "
238
239
then
239
240
debug " incorrect order: $miss "
241
+ process_split_commit " $miss " " " " $indent "
240
242
fi
241
243
done
242
244
}
@@ -340,7 +342,12 @@ find_existing_splits () {
340
342
revs=" $2 "
341
343
main=
342
344
sub=
343
- git log --grep=" ^git-subtree-dir: $dir /*\$ " \
345
+ local grep_format=" ^git-subtree-dir: $dir /*\$ "
346
+ if test -n " $ignore_joins "
347
+ then
348
+ grep_format=" ^Add '$dir /' from commit '"
349
+ fi
350
+ git log --grep=" $grep_format " \
344
351
--no-show-signature --pretty=format:' START %H%n%s%n%n%b%nEND%n' $revs |
345
352
while read a b junk
346
353
do
@@ -534,14 +541,32 @@ copy_or_skip () {
534
541
nonidentical=
535
542
p=
536
543
gotparents=
544
+ copycommit=
537
545
for parent in $newparents
538
546
do
539
547
ptree=$( toptree_for_commit $parent ) || exit $?
540
548
test -z " $ptree " && continue
541
549
if test " $ptree " = " $tree "
542
550
then
543
551
# an identical parent could be used in place of this rev.
544
- identical=" $parent "
552
+ if test -n " $identical "
553
+ then
554
+ # if a previous identical parent was found, check whether
555
+ # one is already an ancestor of the other
556
+ mergebase=$( git merge-base $identical $parent )
557
+ if test " $identical " = " $mergebase "
558
+ then
559
+ # current identical commit is an ancestor of parent
560
+ identical=" $parent "
561
+ elif test " $parent " ! = " $mergebase "
562
+ then
563
+ # no common history; commit must be copied
564
+ copycommit=1
565
+ fi
566
+ else
567
+ # first identical parent detected
568
+ identical=" $parent "
569
+ fi
545
570
else
546
571
nonidentical=" $parent "
547
572
fi
@@ -564,7 +589,6 @@ copy_or_skip () {
564
589
fi
565
590
done
566
591
567
- copycommit=
568
592
if test -n " $identical " && test -n " $nonidentical "
569
593
then
570
594
extras=$( git rev-list --count $identical ..$nonidentical )
@@ -598,6 +622,58 @@ ensure_valid_ref_format () {
598
622
die " '$1 ' does not look like a ref"
599
623
}
600
624
625
+ process_split_commit () {
626
+ local rev=" $1 "
627
+ local parents=" $2 "
628
+ local indent=$3
629
+
630
+ if test $indent -eq 0
631
+ then
632
+ revcount=$(( $revcount + 1 ))
633
+ else
634
+ # processing commit without normal parent information;
635
+ # fetch from repo
636
+ parents=$( git rev-parse " $rev ^@" )
637
+ extracount=$(( $extracount + 1 ))
638
+ fi
639
+
640
+ progress " $revcount /$revmax ($createcount ) [$extracount ]"
641
+
642
+ debug " Processing commit: $rev "
643
+ exists=$( cache_get " $rev " )
644
+ if test -n " $exists "
645
+ then
646
+ debug " prior: $exists "
647
+ return
648
+ fi
649
+ createcount=$(( $createcount + 1 ))
650
+ debug " parents: $parents "
651
+ check_parents " $parents " " $indent "
652
+ newparents=$( cache_get $parents )
653
+ debug " newparents: $newparents "
654
+
655
+ tree=$( subtree_for_commit " $rev " " $dir " )
656
+ debug " tree is: $tree "
657
+
658
+ # ugly. is there no better way to tell if this is a subtree
659
+ # vs. a mainline commit? Does it matter?
660
+ if test -z " $tree "
661
+ then
662
+ set_notree " $rev "
663
+ if test -n " $newparents "
664
+ then
665
+ cache_set " $rev " " $rev "
666
+ fi
667
+ return
668
+ fi
669
+
670
+ newrev=$( copy_or_skip " $rev " " $tree " " $newparents " ) || exit $?
671
+ debug " newrev is: $newrev "
672
+ cache_set " $rev " " $newrev "
673
+ cache_set latest_new " $newrev "
674
+ cache_set latest_old " $rev "
675
+ }
676
+
601
677
cmd_add () {
602
678
if test -e " $dir "
603
679
then
@@ -689,12 +765,7 @@ cmd_split () {
689
765
done
690
766
fi
691
767
692
- if test -n " $ignore_joins "
693
- then
694
- unrevs=
695
- else
696
- unrevs=" $( find_existing_splits " $dir " " $revs " ) "
697
- fi
768
+ unrevs=" $( find_existing_splits " $dir " " $revs " ) "
698
769
699
770
# We can't restrict rev-list to only $dir here, because some of our
700
771
# parents have the $dir contents the root, and those won't match.
@@ -703,45 +774,11 @@ cmd_split () {
703
774
revmax=$( eval " $grl " | wc -l)
704
775
revcount=0
705
776
createcount=0
777
+ extracount=0
706
778
eval " $grl " |
707
779
while read rev parents
708
780
do
709
- revcount=$(( $revcount + 1 ))
710
- progress " $revcount /$revmax ($createcount )"
711
- debug " Processing commit: $rev "
712
- exists=$( cache_get " $rev " )
713
- if test -n " $exists "
714
- then
715
- debug " prior: $exists "
716
- continue
717
- fi
718
- createcount=$(( $createcount + 1 ))
719
- debug " parents: $parents "
720
- newparents=$( cache_get $parents )
721
- debug " newparents: $newparents "
722
-
723
- tree=$( subtree_for_commit " $rev " " $dir " )
724
- debug " tree is: $tree "
725
-
726
- check_parents $parents
727
-
728
- # ugly. is there no better way to tell if this is a subtree
729
- # vs. a mainline commit? Does it matter?
730
- if test -z " $tree "
731
- then
732
- set_notree " $rev "
733
- if test -n " $newparents "
734
- then
735
- cache_set " $rev " " $rev "
736
- fi
737
- continue
738
- fi
739
-
740
- newrev=$( copy_or_skip " $rev " " $tree " " $newparents " ) || exit $?
741
- debug " newrev is: $newrev "
742
- cache_set " $rev " " $newrev "
743
- cache_set latest_new " $newrev "
744
- cache_set latest_old " $rev "
781
+ process_split_commit " $rev " " $parents " 0
745
782
done || exit $?
746
783
747
784
latest_new=$( cache_get latest_new)
0 commit comments