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