2323#include "reachable.h"
2424#include "sha1-array.h"
2525#include "argv-array.h"
26+ #include "mru.h"
2627
2728static const char * pack_usage [] = {
2829 N_ ("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]" ),
@@ -994,7 +995,7 @@ static int want_object_in_pack(const unsigned char *sha1,
994995 struct packed_git * * found_pack ,
995996 off_t * found_offset )
996997{
997- struct packed_git * p ;
998+ struct mru_entry * entry ;
998999 int want ;
9991000
10001001 if (!exclude && local && has_loose_object_nonlocal (sha1 ))
@@ -1011,7 +1012,8 @@ static int want_object_in_pack(const unsigned char *sha1,
10111012 return want ;
10121013 }
10131014
1014- for (p = packed_git ; p ; p = p -> next ) {
1015+ for (entry = packed_git_mru -> head ; entry ; entry = entry -> next ) {
1016+ struct packed_git * p = entry -> item ;
10151017 off_t offset ;
10161018
10171019 if (p == * found_pack )
@@ -1027,6 +1029,8 @@ static int want_object_in_pack(const unsigned char *sha1,
10271029 * found_pack = p ;
10281030 }
10291031 want = want_found_object (exclude , p );
1032+ if (!exclude && want > 0 )
1033+ mru_mark (packed_git_mru , entry );
10301034 if (want != -1 )
10311035 return want ;
10321036 }
@@ -1527,6 +1531,83 @@ static int pack_offset_sort(const void *_a, const void *_b)
15271531 (a -> in_pack_offset > b -> in_pack_offset );
15281532}
15291533
1534+ /*
1535+ * Drop an on-disk delta we were planning to reuse. Naively, this would
1536+ * just involve blanking out the "delta" field, but we have to deal
1537+ * with some extra book-keeping:
1538+ *
1539+ * 1. Removing ourselves from the delta_sibling linked list.
1540+ *
1541+ * 2. Updating our size/type to the non-delta representation. These were
1542+ * either not recorded initially (size) or overwritten with the delta type
1543+ * (type) when check_object() decided to reuse the delta.
1544+ */
1545+ static void drop_reused_delta (struct object_entry * entry )
1546+ {
1547+ struct object_entry * * p = & entry -> delta -> delta_child ;
1548+ struct object_info oi = OBJECT_INFO_INIT ;
1549+
1550+ while (* p ) {
1551+ if (* p == entry )
1552+ * p = (* p )-> delta_sibling ;
1553+ else
1554+ p = & (* p )-> delta_sibling ;
1555+ }
1556+ entry -> delta = NULL ;
1557+
1558+ oi .sizep = & entry -> size ;
1559+ oi .typep = & entry -> type ;
1560+ if (packed_object_info (entry -> in_pack , entry -> in_pack_offset , & oi ) < 0 ) {
1561+ /*
1562+ * We failed to get the info from this pack for some reason;
1563+ * fall back to sha1_object_info, which may find another copy.
1564+ * And if that fails, the error will be recorded in entry->type
1565+ * and dealt with in prepare_pack().
1566+ */
1567+ entry -> type = sha1_object_info (entry -> idx .sha1 , & entry -> size );
1568+ }
1569+ }
1570+
1571+ /*
1572+ * Follow the chain of deltas from this entry onward, throwing away any links
1573+ * that cause us to hit a cycle (as determined by the DFS state flags in
1574+ * the entries).
1575+ */
1576+ static void break_delta_chains (struct object_entry * entry )
1577+ {
1578+ /* If it's not a delta, it can't be part of a cycle. */
1579+ if (!entry -> delta ) {
1580+ entry -> dfs_state = DFS_DONE ;
1581+ return ;
1582+ }
1583+
1584+ switch (entry -> dfs_state ) {
1585+ case DFS_NONE :
1586+ /*
1587+ * This is the first time we've seen the object. We mark it as
1588+ * part of the active potential cycle and recurse.
1589+ */
1590+ entry -> dfs_state = DFS_ACTIVE ;
1591+ break_delta_chains (entry -> delta );
1592+ entry -> dfs_state = DFS_DONE ;
1593+ break ;
1594+
1595+ case DFS_DONE :
1596+ /* object already examined, and not part of a cycle */
1597+ break ;
1598+
1599+ case DFS_ACTIVE :
1600+ /*
1601+ * We found a cycle that needs broken. It would be correct to
1602+ * break any link in the chain, but it's convenient to
1603+ * break this one.
1604+ */
1605+ drop_reused_delta (entry );
1606+ entry -> dfs_state = DFS_DONE ;
1607+ break ;
1608+ }
1609+ }
1610+
15301611static void get_object_details (void )
15311612{
15321613 uint32_t i ;
@@ -1544,6 +1625,13 @@ static void get_object_details(void)
15441625 entry -> no_try_delta = 1 ;
15451626 }
15461627
1628+ /*
1629+ * This must happen in a second pass, since we rely on the delta
1630+ * information for the whole list being completed.
1631+ */
1632+ for (i = 0 ; i < to_pack .nr_objects ; i ++ )
1633+ break_delta_chains (& to_pack .objects [i ]);
1634+
15471635 free (sorted_by_offset );
15481636}
15491637
0 commit comments