18
18
#include "pack-bitmap.h"
19
19
#include "refs.h"
20
20
21
+ #define ALL_INTO_ONE 1
22
+ #define LOOSEN_UNREACHABLE 2
23
+ #define PACK_CRUFT 4
24
+
25
+ static int pack_everything ;
21
26
static int delta_base_offset = 1 ;
22
27
static int pack_kept_objects = -1 ;
23
28
static int write_bitmaps = -1 ;
24
29
static int use_delta_islands ;
25
30
static int run_update_server_info = 1 ;
26
31
static char * packdir , * packtmp_name , * packtmp ;
32
+ static char * cruft_expiration ;
27
33
28
34
static const char * const git_repack_usage [] = {
29
35
N_ ("git repack [<options>]" ),
@@ -305,9 +311,6 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
305
311
die (_ ("could not finish pack-objects to repack promisor objects" ));
306
312
}
307
313
308
- #define ALL_INTO_ONE 1
309
- #define LOOSEN_UNREACHABLE 2
310
-
311
314
struct pack_geometry {
312
315
struct packed_git * * pack ;
313
316
uint32_t pack_nr , pack_alloc ;
@@ -344,6 +347,8 @@ static void init_pack_geometry(struct pack_geometry **geometry_p)
344
347
for (p = get_all_packs (the_repository ); p ; p = p -> next ) {
345
348
if (!pack_kept_objects && p -> pack_keep )
346
349
continue ;
350
+ if (p -> is_cruft )
351
+ continue ;
347
352
348
353
ALLOC_GROW (geometry -> pack ,
349
354
geometry -> pack_nr + 1 ,
@@ -605,6 +610,67 @@ static int write_midx_included_packs(struct string_list *include,
605
610
return finish_command (& cmd );
606
611
}
607
612
613
+ static int write_cruft_pack (const struct pack_objects_args * args ,
614
+ const char * pack_prefix ,
615
+ struct string_list * names ,
616
+ struct string_list * existing_packs ,
617
+ struct string_list * existing_kept_packs )
618
+ {
619
+ struct child_process cmd = CHILD_PROCESS_INIT ;
620
+ struct strbuf line = STRBUF_INIT ;
621
+ struct string_list_item * item ;
622
+ FILE * in , * out ;
623
+ int ret ;
624
+
625
+ prepare_pack_objects (& cmd , args );
626
+
627
+ strvec_push (& cmd .args , "--cruft" );
628
+ if (cruft_expiration )
629
+ strvec_pushf (& cmd .args , "--cruft-expiration=%s" ,
630
+ cruft_expiration );
631
+
632
+ strvec_push (& cmd .args , "--honor-pack-keep" );
633
+ strvec_push (& cmd .args , "--non-empty" );
634
+ strvec_push (& cmd .args , "--max-pack-size=0" );
635
+
636
+ cmd .in = -1 ;
637
+
638
+ ret = start_command (& cmd );
639
+ if (ret )
640
+ return ret ;
641
+
642
+ /*
643
+ * names has a confusing double use: it both provides the list
644
+ * of just-written new packs, and accepts the name of the cruft
645
+ * pack we are writing.
646
+ *
647
+ * By the time it is read here, it contains only the pack(s)
648
+ * that were just written, which is exactly the set of packs we
649
+ * want to consider kept.
650
+ */
651
+ in = xfdopen (cmd .in , "w" );
652
+ for_each_string_list_item (item , names )
653
+ fprintf (in , "%s-%s.pack\n" , pack_prefix , item -> string );
654
+ for_each_string_list_item (item , existing_packs )
655
+ fprintf (in , "-%s.pack\n" , item -> string );
656
+ for_each_string_list_item (item , existing_kept_packs )
657
+ fprintf (in , "%s.pack\n" , item -> string );
658
+ fclose (in );
659
+
660
+ out = xfdopen (cmd .out , "r" );
661
+ while (strbuf_getline_lf (& line , out ) != EOF ) {
662
+ if (line .len != the_hash_algo -> hexsz )
663
+ die (_ ("repack: Expecting full hex object ID lines only "
664
+ "from pack-objects." ));
665
+ string_list_append (names , line .buf );
666
+ }
667
+ fclose (out );
668
+
669
+ strbuf_release (& line );
670
+
671
+ return finish_command (& cmd );
672
+ }
673
+
608
674
int cmd_repack (int argc , const char * * argv , const char * prefix )
609
675
{
610
676
struct child_process cmd = CHILD_PROCESS_INIT ;
@@ -621,7 +687,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
621
687
int show_progress ;
622
688
623
689
/* variables to be filled by option parsing */
624
- int pack_everything = 0 ;
625
690
int delete_redundant = 0 ;
626
691
const char * unpack_unreachable = NULL ;
627
692
int keep_unreachable = 0 ;
@@ -636,6 +701,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
636
701
OPT_BIT ('A' , NULL , & pack_everything ,
637
702
N_ ("same as -a, and turn unreachable objects loose" ),
638
703
LOOSEN_UNREACHABLE | ALL_INTO_ONE ),
704
+ OPT_BIT (0 , "cruft" , & pack_everything ,
705
+ N_ ("same as -a, pack unreachable cruft objects separately" ),
706
+ PACK_CRUFT ),
707
+ OPT_STRING (0 , "cruft-expiration" , & cruft_expiration , N_ ("approxidate" ),
708
+ N_ ("with -C, expire objects older than this" )),
639
709
OPT_BOOL ('d' , NULL , & delete_redundant ,
640
710
N_ ("remove redundant packs, and run git-prune-packed" )),
641
711
OPT_BOOL ('f' , NULL , & po_args .no_reuse_delta ,
@@ -688,6 +758,15 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
688
758
(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE )))
689
759
die (_ ("options '%s' and '%s' cannot be used together" ), "--keep-unreachable" , "-A" );
690
760
761
+ if (pack_everything & PACK_CRUFT ) {
762
+ pack_everything |= ALL_INTO_ONE ;
763
+
764
+ if (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE ))
765
+ die (_ ("options '%s' and '%s' cannot be used together" ), "--cruft" , "-A" );
766
+ if (keep_unreachable )
767
+ die (_ ("options '%s' and '%s' cannot be used together" ), "--cruft" , "-k" );
768
+ }
769
+
691
770
if (write_bitmaps < 0 ) {
692
771
if (!write_midx &&
693
772
(!(pack_everything & ALL_INTO_ONE ) || !is_bare_repository ()))
@@ -771,7 +850,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
771
850
if (pack_everything & ALL_INTO_ONE ) {
772
851
repack_promisor_objects (& po_args , & names );
773
852
774
- if (existing_nonkept_packs .nr && delete_redundant ) {
853
+ if (existing_nonkept_packs .nr && delete_redundant &&
854
+ !(pack_everything & PACK_CRUFT )) {
775
855
for_each_string_list_item (item , & names ) {
776
856
strvec_pushf (& cmd .args , "--keep-pack=%s-%s.pack" ,
777
857
packtmp_name , item -> string );
@@ -833,6 +913,21 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
833
913
if (!names .nr && !po_args .quiet )
834
914
printf_ln (_ ("Nothing new to pack." ));
835
915
916
+ if (pack_everything & PACK_CRUFT ) {
917
+ const char * pack_prefix ;
918
+ if (!skip_prefix (packtmp , packdir , & pack_prefix ))
919
+ die (_ ("pack prefix %s does not begin with objdir %s" ),
920
+ packtmp , packdir );
921
+ if (* pack_prefix == '/' )
922
+ pack_prefix ++ ;
923
+
924
+ ret = write_cruft_pack (& po_args , pack_prefix , & names ,
925
+ & existing_nonkept_packs ,
926
+ & existing_kept_packs );
927
+ if (ret )
928
+ return ret ;
929
+ }
930
+
836
931
for_each_string_list_item (item , & names ) {
837
932
item -> util = (void * )(uintptr_t )populate_pack_exts (item -> string );
838
933
}
0 commit comments