@@ -2023,35 +2023,50 @@ struct ref_to_prune {
2023
2023
2024
2024
struct pack_refs_cb_data {
2025
2025
unsigned int flags ;
2026
+ struct ref_dir * packed_refs ;
2026
2027
struct ref_to_prune * ref_to_prune ;
2027
- int fd ;
2028
2028
};
2029
2029
2030
- static int pack_one_ref (struct ref_entry * entry , void * cb_data )
2030
+ /*
2031
+ * An each_ref_entry_fn that is run over loose references only. If
2032
+ * the loose reference can be packed, add an entry in the packed ref
2033
+ * cache. If the reference should be pruned, also add it to
2034
+ * ref_to_prune in the pack_refs_cb_data.
2035
+ */
2036
+ static int pack_if_possible_fn (struct ref_entry * entry , void * cb_data )
2031
2037
{
2032
2038
struct pack_refs_cb_data * cb = cb_data ;
2033
2039
enum peel_status peel_status ;
2040
+ struct ref_entry * packed_entry ;
2034
2041
int is_tag_ref = !prefixcmp (entry -> name , "refs/tags/" );
2035
2042
2036
- /* ALWAYS pack refs that were already packed or are tags */
2037
- if (!(cb -> flags & PACK_REFS_ALL ) && !is_tag_ref &&
2038
- !(entry -> flag & REF_ISPACKED ))
2043
+ /* ALWAYS pack tags */
2044
+ if (!(cb -> flags & PACK_REFS_ALL ) && !is_tag_ref )
2039
2045
return 0 ;
2040
2046
2041
2047
/* Do not pack symbolic or broken refs: */
2042
2048
if ((entry -> flag & REF_ISSYMREF ) || !ref_resolves_to_object (entry ))
2043
2049
return 0 ;
2044
2050
2051
+ /* Add a packed ref cache entry equivalent to the loose entry. */
2045
2052
peel_status = peel_entry (entry , 1 );
2046
2053
if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG )
2047
2054
die ("internal error peeling reference %s (%s)" ,
2048
2055
entry -> name , sha1_to_hex (entry -> u .value .sha1 ));
2049
- write_packed_entry (cb -> fd , entry -> name , entry -> u .value .sha1 ,
2050
- peel_status == PEEL_PEELED ?
2051
- entry -> u .value .peeled : NULL );
2056
+ packed_entry = find_ref (cb -> packed_refs , entry -> name );
2057
+ if (packed_entry ) {
2058
+ /* Overwrite existing packed entry with info from loose entry */
2059
+ packed_entry -> flag = REF_ISPACKED | REF_KNOWS_PEELED ;
2060
+ hashcpy (packed_entry -> u .value .sha1 , entry -> u .value .sha1 );
2061
+ } else {
2062
+ packed_entry = create_ref_entry (entry -> name , entry -> u .value .sha1 ,
2063
+ REF_ISPACKED | REF_KNOWS_PEELED , 0 );
2064
+ add_ref (cb -> packed_refs , packed_entry );
2065
+ }
2066
+ hashcpy (packed_entry -> u .value .peeled , entry -> u .value .peeled );
2052
2067
2053
- /* If the ref was already packed, there is no need to prune it . */
2054
- if ((cb -> flags & PACK_REFS_PRUNE ) && !( entry -> flag & REF_ISPACKED ) ) {
2068
+ /* Schedule the loose reference for pruning if requested . */
2069
+ if ((cb -> flags & PACK_REFS_PRUNE )) {
2055
2070
int namelen = strlen (entry -> name ) + 1 ;
2056
2071
struct ref_to_prune * n = xcalloc (1 , sizeof (* n ) + namelen );
2057
2072
hashcpy (n -> sha1 , entry -> u .value .sha1 );
@@ -2118,16 +2133,21 @@ static struct lock_file packlock;
2118
2133
int pack_refs (unsigned int flags )
2119
2134
{
2120
2135
struct pack_refs_cb_data cbdata ;
2136
+ int fd ;
2121
2137
2122
2138
memset (& cbdata , 0 , sizeof (cbdata ));
2123
2139
cbdata .flags = flags ;
2124
2140
2125
- cbdata .fd = hold_lock_file_for_update (& packlock , git_path ("packed-refs" ),
2126
- LOCK_DIE_ON_ERROR );
2141
+ fd = hold_lock_file_for_update (& packlock , git_path ("packed-refs" ),
2142
+ LOCK_DIE_ON_ERROR );
2143
+ cbdata .packed_refs = get_packed_refs (& ref_cache );
2127
2144
2128
- write_or_die (cbdata .fd , PACKED_REFS_HEADER , strlen (PACKED_REFS_HEADER ));
2145
+ do_for_each_entry_in_dir (get_loose_refs (& ref_cache ), 0 ,
2146
+ pack_if_possible_fn , & cbdata );
2147
+
2148
+ write_or_die (fd , PACKED_REFS_HEADER , strlen (PACKED_REFS_HEADER ));
2149
+ do_for_each_entry_in_dir (cbdata .packed_refs , 0 , write_packed_entry_fn , & fd );
2129
2150
2130
- do_for_each_entry (& ref_cache , "" , pack_one_ref , & cbdata );
2131
2151
if (commit_lock_file (& packlock ) < 0 )
2132
2152
die_errno ("unable to overwrite old ref-pack file" );
2133
2153
prune_refs (cbdata .ref_to_prune );
0 commit comments