@@ -1883,6 +1883,7 @@ static void my_run_index_pack(struct gh__request_params *params UNUSED,
1883
1883
1884
1884
static void my_finalize_packfile (struct gh__request_params * params ,
1885
1885
struct gh__response_status * status ,
1886
+ int b_keep ,
1886
1887
const struct strbuf * temp_path_pack ,
1887
1888
const struct strbuf * temp_path_idx ,
1888
1889
struct strbuf * final_path_pack ,
@@ -1902,6 +1903,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
1902
1903
return ;
1903
1904
}
1904
1905
1906
+ if (b_keep ) {
1907
+ struct strbuf keep = STRBUF_INIT ;
1908
+ int fd_keep ;
1909
+
1910
+ strbuf_addbuf (& keep , final_path_pack );
1911
+ strbuf_strip_suffix (& keep , ".pack" );
1912
+ strbuf_addstr (& keep , ".keep" );
1913
+
1914
+ fd_keep = xopen (keep .buf , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1915
+ if (fd_keep >= 0 )
1916
+ close (fd_keep );
1917
+
1918
+ strbuf_release (& keep );
1919
+ }
1920
+
1905
1921
if (params -> result_list ) {
1906
1922
struct strbuf result_msg = STRBUF_INIT ;
1907
1923
@@ -1954,7 +1970,7 @@ static void install_packfile(struct gh__request_params *params,
1954
1970
create_final_packfile_pathnames ("vfs" , packfile_checksum .buf , NULL ,
1955
1971
& final_path_pack , & final_path_idx ,
1956
1972
& final_filename );
1957
- my_finalize_packfile (params , status ,
1973
+ my_finalize_packfile (params , status , 0 ,
1958
1974
& temp_path_pack , & temp_path_idx ,
1959
1975
& final_path_pack , & final_path_idx ,
1960
1976
& final_filename );
@@ -2050,6 +2066,12 @@ struct ph {
2050
2066
2051
2067
/*
2052
2068
* Extract the next packfile from the multipack.
2069
+ * Install {.pack, .idx, .keep} set.
2070
+ *
2071
+ * Mark each successfully installed prefetch pack as .keep it as installed
2072
+ * in case we have errors decoding/indexing later packs within the received
2073
+ * multipart file. (A later pass can delete the unnecessary .keep files
2074
+ * from this and any previous invocations.)
2053
2075
*/
2054
2076
static void extract_packfile_from_multipack (
2055
2077
struct gh__request_params * params ,
@@ -2146,7 +2168,7 @@ static void extract_packfile_from_multipack(
2146
2168
2147
2169
} else {
2148
2170
/*
2149
- * Server send the .idx immediately after the .pack in the
2171
+ * Server sent the .idx immediately after the .pack in the
2150
2172
* data stream. I'm tempted to verify it, but that defeats
2151
2173
* the purpose of having it cached...
2152
2174
*/
@@ -2169,7 +2191,7 @@ static void extract_packfile_from_multipack(
2169
2191
& final_filename );
2170
2192
strbuf_release (& buf_timestamp );
2171
2193
2172
- my_finalize_packfile (params , status ,
2194
+ my_finalize_packfile (params , status , 1 ,
2173
2195
& temp_path_pack , & temp_path_idx ,
2174
2196
& final_path_pack , & final_path_idx ,
2175
2197
& final_filename );
@@ -2184,6 +2206,56 @@ static void extract_packfile_from_multipack(
2184
2206
strbuf_release (& final_filename );
2185
2207
}
2186
2208
2209
+ struct keep_files_data {
2210
+ timestamp_t max_timestamp ;
2211
+ int pos_of_max ;
2212
+ struct string_list * keep_files ;
2213
+ };
2214
+
2215
+ static void cb_keep_files (const char * full_path , size_t full_path_len UNUSED ,
2216
+ const char * file_path , void * void_data )
2217
+ {
2218
+ struct keep_files_data * data = void_data ;
2219
+ const char * val ;
2220
+ timestamp_t t ;
2221
+
2222
+ /*
2223
+ * We expect prefetch packfiles named like:
2224
+ *
2225
+ * prefetch-<seconds>-<checksum>.keep
2226
+ */
2227
+ if (!skip_prefix (file_path , "prefetch-" , & val ))
2228
+ return ;
2229
+ if (!ends_with (val , ".keep" ))
2230
+ return ;
2231
+
2232
+ t = strtol (val , NULL , 10 );
2233
+ if (t > data -> max_timestamp ) {
2234
+ data -> pos_of_max = data -> keep_files -> nr ;
2235
+ data -> max_timestamp = t ;
2236
+ }
2237
+
2238
+ string_list_append (data -> keep_files , full_path );
2239
+ }
2240
+
2241
+ static void delete_stale_keep_files (
2242
+ struct gh__request_params * params UNUSED ,
2243
+ struct gh__response_status * status UNUSED )
2244
+ {
2245
+ struct string_list keep_files = STRING_LIST_INIT_DUP ;
2246
+ struct keep_files_data data = { 0 , 0 , & keep_files };
2247
+ size_t k ;
2248
+
2249
+ for_each_file_in_pack_dir (gh__global .buf_odb_path .buf ,
2250
+ cb_keep_files , & data );
2251
+ for (k = 0 ; k < keep_files .nr ; k ++ ) {
2252
+ if ((ssize_t )k != data .pos_of_max )
2253
+ unlink (keep_files .items [k ].string );
2254
+ }
2255
+
2256
+ string_list_clear (& keep_files , 0 );
2257
+ }
2258
+
2187
2259
/*
2188
2260
* Cut apart the received multipart response into individual packfiles
2189
2261
* and install each one.
@@ -2202,6 +2274,7 @@ static void install_prefetch(struct gh__request_params *params,
2202
2274
unsigned short np ;
2203
2275
unsigned short k ;
2204
2276
int fd = -1 ;
2277
+ int nr_installed = 0 ;
2205
2278
2206
2279
struct strbuf temp_path_mp = STRBUF_INIT ;
2207
2280
@@ -2246,9 +2319,13 @@ static void install_prefetch(struct gh__request_params *params,
2246
2319
display_progress (params -> progress , k + 1 );
2247
2320
if (status -> ec != GH__ERROR_CODE__OK )
2248
2321
break ;
2322
+ nr_installed ++ ;
2249
2323
}
2250
2324
stop_progress (& params -> progress );
2251
2325
2326
+ if (nr_installed )
2327
+ delete_stale_keep_files (params , status );
2328
+
2252
2329
cleanup :
2253
2330
if (fd != -1 )
2254
2331
close (fd );
0 commit comments