891
git repack --geometric=2 -d --write-midx --write-bitmap-index
892
'
893
894
+test_expect_success 'repack --geometric --cruft combines packs and writes cruft' '
895
+ git init geometric-cruft-basic &&
896
+ (
897
+ cd geometric-cruft-basic &&
898
+
899
+ test_commit A &&
900
+ test_commit B &&
901
+
902
+ B="$(git rev-parse B)" &&
903
+
904
+ git reset --hard $B^ &&
905
+ git tag -d B &&
906
+ git reflog expire --all --expire=all &&
907
+
908
+ # Initial state: one non-cruft pack, one cruft pack.
909
+ git repack -d --cruft &&
910
+
911
+ ls $packdir/pack-*.mtimes >cruft.before &&
912
+ test_line_count = 1 cruft.before &&
913
+
914
+ test_commit C &&
915
+ git repack &&
916
+
917
+ # At this point we have three packs:
918
+ # - the non-cruft pack from A
919
+ # - the cruft pack from B
920
+ # - a new non-cruft pack from C
921
+ #
922
+ # The two non-cruft packs are not in a geometric
923
+ # progression, so they should be rolled up.
924
+ git repack -d --geometric=2 --cruft &&
925
+
926
+ # The old cruft pack for B is retained, since the
927
+ # geometric repack does not touch cruft packs.
928
+ ls $packdir/pack-*.mtimes >cruft.after &&
929
+ test_line_count = 1 cruft.after &&
930
+
931
+ # Ensure that all reachable objects are present.
932
+ git fsck
933
+ )
934
+'
935
+
936
+test_expect_success 'repack --geometric --cruft writes new cruft for loose unreachable' '
937
+ git init geometric-cruft-new-cruft &&
938
+ (
939
+ cd geometric-cruft-new-cruft &&
940
+
941
+ git config set maintenance.auto false &&
942
+
943
+ test_commit A &&
944
+ git repack &&
945
+
946
+ test_commit B &&
947
+ git repack &&
948
+
949
+ # Create an unreachable commit whose objects are
950
+ # still loose (never packed).
951
+ test_commit C &&
952
+ C="$(git rev-parse C)" &&
953
+ git reset --hard $C^ &&
954
+ git tag -d C &&
955
+ git reflog expire --all --expire=all &&
956
+
957
+ # At this point we have two non-cruft packs of
958
+ # similar size that are not in geometric progression,
959
+ # and loose unreachable objects from commit C.
960
+ ls $packdir/pack-*.idx >packs.before &&
961
+ test_line_count = 2 packs.before &&
962
+
963
+ # Geometric+cruft repack should roll up the two
964
+ # non-cruft packs and write a new cruft pack for C
965
+ # (whose objects are loose and unreachable).
966
+ git repack -d --geometric=2 --cruft &&
967
+
968
+ ls $packdir/pack-*.mtimes >cruft.after &&
969
+ test_line_count = 1 cruft.after &&
970
+
971
+ git fsck
972
+ )
973
+'
974
+
975
+test_expect_success 'repack --geometric --cruft -d deletes rolled-up packs' '
976
+ git init geometric-cruft-delete &&
977
+ (
978
+ cd geometric-cruft-delete &&
979
+
980
+ test_commit A &&
981
+ git repack -d &&
982
+
983
+ test_commit B &&
984
+ git repack -d &&
985
+
986
+ ls $packdir/pack-*.idx >before &&
987
+
988
+ git repack -d --geometric=2 --cruft &&
989
+
990
+ # Two packs should have been rolled into one. No cruft
991
+ # pack is written because there are no unreachable objects.
992
+ ls $packdir/pack-*.idx >after &&
993
+ test_line_count = 1 after &&
994
+
995
+ # The rolled-up packs should be gone.
996
+ ! test_cmp before after
997
+ )
998
+'
999
+
1000
+test_expect_success 'repack --geometric --cruft collects loose unreachable objects' '
1001
+ git init geometric-cruft-loose &&
1002
+ (
1003
+ cd geometric-cruft-loose &&
1004
+
1005
+ test_commit A &&
1006
+ git repack -d &&
1007
+
1008
+ test_commit B &&
1009
+ git repack &&
1010
+
1011
+ # Create a loose unreachable object by making it
1012
+ # orphaned (not in any pack).
1013
+ loose="$(echo "cruft object" | git hash-object -w --stdin)" &&
1014
+
1015
+ # We have two non-cruft packs and a loose unreachable
1016
+ # object. The geometric+cruft repack should roll up
1017
+ # the packs AND write a cruft pack for the loose
1018
+ # unreachable object.
1019
+ git repack -d --geometric=2 --cruft &&
1020
+
1021
+ ls $packdir/pack-*.mtimes >cruft.packs &&
1022
+ test_line_count = 1 cruft.packs &&
1023
+
1024
+ git fsck
1025
+ )
1026
+'
1027
+
1028
+test_expect_success 'repack --geometric --cruft accumulates cruft packs' '
1029
+ git init geometric-cruft-accumulate &&
1030
+ (
1031
+ cd geometric-cruft-accumulate &&
1032
+
1033
+ git config set maintenance.auto false &&
1034
+
1035
+ test_commit A &&
1036
+ git repack &&
1037
+
1038
+ # First round: create unreachable objects and do a
1039
+ # geometric+cruft repack.
1040
+ unreachable_1="$(echo "cruft 1" | git hash-object -w --stdin)" &&
1041
+ git repack -d --geometric=2 --cruft &&
1042
+
1043
+ ls $packdir/pack-*.mtimes >cruft.1 &&
1044
+ test_line_count = 1 cruft.1 &&
1045
+
1046
+ test_commit B &&
1047
+ git repack &&
1048
+
1049
+ # Second round: create more unreachable objects and
1050
+ # repack again. The old cruft pack should be retained
1051
+ # and a new one written.
1052
+ unreachable_2="$(echo "cruft 2" | git hash-object -w --stdin)" &&
1053
+ git repack -d --geometric=2 --cruft &&
1054
+
1055
+ ls $packdir/pack-*.mtimes >cruft.2 &&
1056
+ test_line_count = 2 cruft.2 &&
1057
+
1058
+ git fsck
1059
+ )
1060
+'
1061
+
1062
+test_expect_success 'repack --geometric --cruft --combine-cruft-below-size' '
1063
+ git init geometric-cruft-combine &&
1064
+ (
1065
+ cd geometric-cruft-combine &&
1066
+
1067
+ git config set maintenance.auto false &&
1068
+
1069
+ test_commit A &&
1070
+ git repack &&
1071
+
1072
+ # Create a small cruft pack.
1073
+ unreachable_1="$(echo "cruft 1" | git hash-object -w --stdin)" &&
1074
+ git repack -d --geometric=2 --cruft &&
1075
+
1076
+ ls $packdir/pack-*.mtimes >cruft.before &&
1077
+ test_line_count = 1 cruft.before &&
1078
+
1079
+ test_commit B &&
1080
+ git repack &&
1081
+
1082
+ # Create another small cruft pack.
1083
+ unreachable_2="$(echo "cruft 2" | git hash-object -w --stdin)" &&
1084
+ git repack -d --geometric=2 --cruft &&
1085
+
1086
+ ls $packdir/pack-*.mtimes >cruft.mid &&
1087
+ test_line_count = 2 cruft.mid &&
1088
+
1089
+ test_commit C &&
1090
+ git repack &&
1091
+
1092
+ # With --combine-cruft-below-size, the two small cruft
1093
+ # packs should be combined into one.
1094
+ unreachable_3="$(echo "cruft 3" | git hash-object -w --stdin)" &&
1095
+ git repack -d --geometric=2 --cruft \
1096
+ --combine-cruft-below-size=10M &&
1097
+
1098
+ ls $packdir/pack-*.mtimes >cruft.after &&
1099
+ test_line_count = 1 cruft.after &&
1100
+
1101
+ git fsck
1102
+ )
1103
+'
1104
+
1105
+test_expect_success 'repack --geometric --cruft --expire-to' '
1106
+ git init geometric-cruft-expire-to &&
1107
+ (
1108
+ cd geometric-cruft-expire-to &&
1109
+
1110
+ git config set maintenance.auto false &&
1111
+
1112
+ test_commit A &&
1113
+ git repack &&
1114
+
1115
+ test_commit B &&
1116
+ git repack &&
1117
+
1118
+ # Create unreachable objects and record them.
1119
+ test_commit C &&
1120
+ C="$(git rev-parse C)" &&
1121
+ git rev-list --objects --no-object-names B..C >unreachable.raw &&
1122
+ sort unreachable.raw >unreachable.want &&
1123
+
1124
+ git reset --hard $C^ &&
1125
+ git tag -d C &&
1126
+ git reflog expire --all --expire=all &&
1127
+
1128
+ git init --bare expired.git &&
1129
+ git repack -d --geometric=2 --cruft \
1130
+ --cruft-expiration=now \
1131
+ --expire-to="expired.git/objects/pack/pack" &&
1132
+
1133
+ # The expired objects should appear in the
1134
+ # expire-to location.
1135
+ expired="$(ls expired.git/objects/pack/pack-*.idx)" &&
1136
+ test_path_is_file "${expired%.idx}.mtimes" &&
1137
+ git show-index <"$expired" >expired.raw &&
1138
+ cut -d" " -f2 expired.raw | sort >expired.objects &&
1139
+ test_cmp unreachable.want expired.objects &&
1140
+
1141
+ git fsck
1142
+ )
1143
+'
1144
+
1145
test_done