@@ -21,7 +21,7 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\
2121 [--window=N] [--window-memory=N] [--depth=N] \n\
2222 [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
2323 [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
24- [--stdout | base-name] [<ref-list | <object-list]" ;
24+ [--stdout | base-name] [--keep-unreachable] [ <ref-list | <object-list]" ;
2525
2626struct object_entry {
2727 struct pack_idx_entry idx ;
@@ -57,7 +57,7 @@ static struct object_entry **written_list;
5757static uint32_t nr_objects , nr_alloc , nr_result , nr_written ;
5858
5959static int non_empty ;
60- static int no_reuse_delta , no_reuse_object ;
60+ static int no_reuse_delta , no_reuse_object , keep_unreachable ;
6161static int local ;
6262static int incremental ;
6363static int allow_ofs_delta ;
@@ -1625,22 +1625,106 @@ static void read_object_list_from_stdin(void)
16251625 }
16261626}
16271627
1628+ #define OBJECT_ADDED (1u<<20)
1629+
16281630static void show_commit (struct commit * commit )
16291631{
16301632 add_object_entry (commit -> object .sha1 , OBJ_COMMIT , NULL , 0 );
1633+ commit -> object .flags |= OBJECT_ADDED ;
16311634}
16321635
16331636static void show_object (struct object_array_entry * p )
16341637{
16351638 add_preferred_base_object (p -> name );
16361639 add_object_entry (p -> item -> sha1 , p -> item -> type , p -> name , 0 );
1640+ p -> item -> flags |= OBJECT_ADDED ;
16371641}
16381642
16391643static void show_edge (struct commit * commit )
16401644{
16411645 add_preferred_base (commit -> object .sha1 );
16421646}
16431647
1648+ struct in_pack_object {
1649+ off_t offset ;
1650+ struct object * object ;
1651+ };
1652+
1653+ struct in_pack {
1654+ int alloc ;
1655+ int nr ;
1656+ struct in_pack_object * array ;
1657+ };
1658+
1659+ static void mark_in_pack_object (struct object * object , struct packed_git * p , struct in_pack * in_pack )
1660+ {
1661+ in_pack -> array [in_pack -> nr ].offset = find_pack_entry_one (object -> sha1 , p );
1662+ in_pack -> array [in_pack -> nr ].object = object ;
1663+ in_pack -> nr ++ ;
1664+ }
1665+
1666+ /*
1667+ * Compare the objects in the offset order, in order to emulate the
1668+ * "git-rev-list --objects" output that produced the pack originally.
1669+ */
1670+ static int ofscmp (const void * a_ , const void * b_ )
1671+ {
1672+ struct in_pack_object * a = (struct in_pack_object * )a_ ;
1673+ struct in_pack_object * b = (struct in_pack_object * )b_ ;
1674+
1675+ if (a -> offset < b -> offset )
1676+ return -1 ;
1677+ else if (a -> offset > b -> offset )
1678+ return 1 ;
1679+ else
1680+ return hashcmp (a -> object -> sha1 , b -> object -> sha1 );
1681+ }
1682+
1683+ static void add_objects_in_unpacked_packs (struct rev_info * revs )
1684+ {
1685+ struct packed_git * p ;
1686+ struct in_pack in_pack ;
1687+ uint32_t i ;
1688+
1689+ memset (& in_pack , 0 , sizeof (in_pack ));
1690+
1691+ for (p = packed_git ; p ; p = p -> next ) {
1692+ const unsigned char * sha1 ;
1693+ struct object * o ;
1694+
1695+ for (i = 0 ; i < revs -> num_ignore_packed ; i ++ ) {
1696+ if (matches_pack_name (p , revs -> ignore_packed [i ]))
1697+ break ;
1698+ }
1699+ if (revs -> num_ignore_packed <= i )
1700+ continue ;
1701+ if (open_pack_index (p ))
1702+ die ("cannot open pack index" );
1703+
1704+ ALLOC_GROW (in_pack .array ,
1705+ in_pack .nr + p -> num_objects ,
1706+ in_pack .alloc );
1707+
1708+ for (i = 0 ; i < p -> num_objects ; i ++ ) {
1709+ sha1 = nth_packed_object_sha1 (p , i );
1710+ o = lookup_unknown_object (sha1 );
1711+ if (!(o -> flags & OBJECT_ADDED ))
1712+ mark_in_pack_object (o , p , & in_pack );
1713+ o -> flags |= OBJECT_ADDED ;
1714+ }
1715+ }
1716+
1717+ if (in_pack .nr ) {
1718+ qsort (in_pack .array , in_pack .nr , sizeof (in_pack .array [0 ]),
1719+ ofscmp );
1720+ for (i = 0 ; i < in_pack .nr ; i ++ ) {
1721+ struct object * o = in_pack .array [i ].object ;
1722+ add_object_entry (o -> sha1 , o -> type , "" , 0 );
1723+ }
1724+ }
1725+ free (in_pack .array );
1726+ }
1727+
16441728static void get_object_list (int ac , const char * * av )
16451729{
16461730 struct rev_info revs ;
@@ -1672,6 +1756,9 @@ static void get_object_list(int ac, const char **av)
16721756 prepare_revision_walk (& revs );
16731757 mark_edges_uninteresting (revs .commits , & revs , show_edge );
16741758 traverse_commit_list (& revs , show_commit , show_object );
1759+
1760+ if (keep_unreachable )
1761+ add_objects_in_unpacked_packs (& revs );
16751762}
16761763
16771764static int adjust_perm (const char * path , mode_t mode )
@@ -1789,6 +1876,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
17891876 use_internal_rev_list = 1 ;
17901877 continue ;
17911878 }
1879+ if (!strcmp ("--keep-unreachable" , arg )) {
1880+ keep_unreachable = 1 ;
1881+ continue ;
1882+ }
17921883 if (!strcmp ("--unpacked" , arg ) ||
17931884 !prefixcmp (arg , "--unpacked=" ) ||
17941885 !strcmp ("--reflog" , arg ) ||
0 commit comments