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