@@ -1998,6 +1998,23 @@ static void write_packed_entry(int fd, char *refname, unsigned char *sha1,
1998
1998
}
1999
1999
}
2000
2000
2001
+ /*
2002
+ * An each_ref_entry_fn that writes the entry to a packed-refs file.
2003
+ */
2004
+ static int write_packed_entry_fn (struct ref_entry * entry , void * cb_data )
2005
+ {
2006
+ int * fd = cb_data ;
2007
+ enum peel_status peel_status = peel_entry (entry , 0 );
2008
+
2009
+ if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG )
2010
+ error ("internal error: %s is not a valid packed reference!" ,
2011
+ entry -> name );
2012
+ write_packed_entry (* fd , entry -> name , entry -> u .value .sha1 ,
2013
+ peel_status == PEEL_PEELED ?
2014
+ entry -> u .value .peeled : NULL );
2015
+ return 0 ;
2016
+ }
2017
+
2001
2018
struct ref_to_prune {
2002
2019
struct ref_to_prune * next ;
2003
2020
unsigned char sha1 [20 ];
@@ -2117,14 +2134,25 @@ int pack_refs(unsigned int flags)
2117
2134
return 0 ;
2118
2135
}
2119
2136
2120
- static int repack_ref_fn (struct ref_entry * entry , void * cb_data )
2137
+ /*
2138
+ * If entry is no longer needed in packed-refs, add it to the string
2139
+ * list pointed to by cb_data. Reasons for deleting entries:
2140
+ *
2141
+ * - Entry is broken.
2142
+ * - Entry is overridden by a loose ref.
2143
+ * - Entry does not point at a valid object.
2144
+ *
2145
+ * In the first and third cases, also emit an error message because these
2146
+ * are indications of repository corruption.
2147
+ */
2148
+ static int curate_packed_ref_fn (struct ref_entry * entry , void * cb_data )
2121
2149
{
2122
- int * fd = cb_data ;
2123
- enum peel_status peel_status ;
2150
+ struct string_list * refs_to_delete = cb_data ;
2124
2151
2125
2152
if (entry -> flag & REF_ISBROKEN ) {
2126
2153
/* This shouldn't happen to packed refs. */
2127
2154
error ("%s is broken!" , entry -> name );
2155
+ string_list_append (refs_to_delete , entry -> name );
2128
2156
return 0 ;
2129
2157
}
2130
2158
if (!has_sha1_file (entry -> u .value .sha1 )) {
@@ -2134,7 +2162,7 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
2134
2162
if (read_ref_full (entry -> name , sha1 , 0 , & flags ))
2135
2163
/* We should at least have found the packed ref. */
2136
2164
die ("Internal error" );
2137
- if ((flags & REF_ISSYMREF ) || !(flags & REF_ISPACKED ))
2165
+ if ((flags & REF_ISSYMREF ) || !(flags & REF_ISPACKED )) {
2138
2166
/*
2139
2167
* This packed reference is overridden by a
2140
2168
* loose reference, so it is OK that its value
@@ -2143,9 +2171,11 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
2143
2171
* collected. For this purpose we don't even
2144
2172
* care whether the loose reference itself is
2145
2173
* invalid, broken, symbolic, etc. Silently
2146
- * omit the packed reference from the output .
2174
+ * remove the packed reference.
2147
2175
*/
2176
+ string_list_append (refs_to_delete , entry -> name );
2148
2177
return 0 ;
2178
+ }
2149
2179
/*
2150
2180
* There is no overriding loose reference, so the fact
2151
2181
* that this reference doesn't refer to a valid object
@@ -2154,21 +2184,19 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
2154
2184
* the output.
2155
2185
*/
2156
2186
error ("%s does not point to a valid object!" , entry -> name );
2187
+ string_list_append (refs_to_delete , entry -> name );
2157
2188
return 0 ;
2158
2189
}
2159
2190
2160
- peel_status = peel_entry (entry , 0 );
2161
- write_packed_entry (* fd , entry -> name , entry -> u .value .sha1 ,
2162
- peel_status == PEEL_PEELED ?
2163
- entry -> u .value .peeled : NULL );
2164
-
2165
2191
return 0 ;
2166
2192
}
2167
2193
2168
2194
static int repack_without_ref (const char * refname )
2169
2195
{
2170
2196
int fd ;
2171
2197
struct ref_dir * packed ;
2198
+ struct string_list refs_to_delete = STRING_LIST_INIT_DUP ;
2199
+ struct string_list_item * ref_to_delete ;
2172
2200
2173
2201
if (!get_packed_ref (refname ))
2174
2202
return 0 ; /* refname does not exist in packed refs */
@@ -2180,7 +2208,8 @@ static int repack_without_ref(const char *refname)
2180
2208
}
2181
2209
clear_packed_ref_cache (& ref_cache );
2182
2210
packed = get_packed_refs (& ref_cache );
2183
- /* Remove refname from the cache. */
2211
+
2212
+ /* Remove refname from the cache: */
2184
2213
if (remove_entry (packed , refname ) == -1 ) {
2185
2214
/*
2186
2215
* The packed entry disappeared while we were
@@ -2189,8 +2218,17 @@ static int repack_without_ref(const char *refname)
2189
2218
rollback_lock_file (& packlock );
2190
2219
return 0 ;
2191
2220
}
2221
+
2222
+ /* Remove any other accumulated cruft: */
2223
+ do_for_each_entry_in_dir (packed , 0 , curate_packed_ref_fn , & refs_to_delete );
2224
+ for_each_string_list_item (ref_to_delete , & refs_to_delete ) {
2225
+ if (remove_entry (packed , ref_to_delete -> string ) == -1 )
2226
+ die ("internal error" );
2227
+ }
2228
+
2229
+ /* Write what remains: */
2192
2230
write_or_die (fd , PACKED_REFS_HEADER , strlen (PACKED_REFS_HEADER ));
2193
- do_for_each_entry_in_dir (packed , 0 , repack_ref_fn , & fd );
2231
+ do_for_each_entry_in_dir (packed , 0 , write_packed_entry_fn , & fd );
2194
2232
return commit_lock_file (& packlock );
2195
2233
}
2196
2234
0 commit comments