@@ -1864,6 +1864,7 @@ static void my_run_index_pack(struct gh__request_params *params,
1864
1864
1865
1865
static void my_finalize_packfile (struct gh__request_params * params ,
1866
1866
struct gh__response_status * status ,
1867
+ int b_keep ,
1867
1868
const struct strbuf * temp_path_pack ,
1868
1869
const struct strbuf * temp_path_idx ,
1869
1870
struct strbuf * final_path_pack ,
@@ -1883,6 +1884,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
1883
1884
return ;
1884
1885
}
1885
1886
1887
+ if (b_keep ) {
1888
+ struct strbuf keep = STRBUF_INIT ;
1889
+ int fd_keep ;
1890
+
1891
+ strbuf_addbuf (& keep , final_path_pack );
1892
+ strbuf_strip_suffix (& keep , ".pack" );
1893
+ strbuf_addstr (& keep , ".keep" );
1894
+
1895
+ fd_keep = xopen (keep .buf , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1896
+ if (fd_keep >= 0 )
1897
+ close (fd_keep );
1898
+
1899
+ strbuf_release (& keep );
1900
+ }
1901
+
1886
1902
if (params -> result_list ) {
1887
1903
struct strbuf result_msg = STRBUF_INIT ;
1888
1904
@@ -1935,7 +1951,7 @@ static void install_packfile(struct gh__request_params *params,
1935
1951
create_final_packfile_pathnames ("vfs" , packfile_checksum .buf , NULL ,
1936
1952
& final_path_pack , & final_path_idx ,
1937
1953
& final_filename );
1938
- my_finalize_packfile (params , status ,
1954
+ my_finalize_packfile (params , status , 0 ,
1939
1955
& temp_path_pack , & temp_path_idx ,
1940
1956
& final_path_pack , & final_path_idx ,
1941
1957
& final_filename );
@@ -2031,6 +2047,12 @@ struct ph {
2031
2047
2032
2048
/*
2033
2049
* Extract the next packfile from the multipack.
2050
+ * Install {.pack, .idx, .keep} set.
2051
+ *
2052
+ * Mark each successfully installed prefetch pack as .keep it as installed
2053
+ * in case we have errors decoding/indexing later packs within the received
2054
+ * multipart file. (A later pass can delete the unnecessary .keep files
2055
+ * from this and any previous invocations.)
2034
2056
*/
2035
2057
static void extract_packfile_from_multipack (
2036
2058
struct gh__request_params * params ,
@@ -2125,7 +2147,7 @@ static void extract_packfile_from_multipack(
2125
2147
2126
2148
} else {
2127
2149
/*
2128
- * Server send the .idx immediately after the .pack in the
2150
+ * Server sent the .idx immediately after the .pack in the
2129
2151
* data stream. I'm tempted to verify it, but that defeats
2130
2152
* the purpose of having it cached...
2131
2153
*/
@@ -2147,7 +2169,7 @@ static void extract_packfile_from_multipack(
2147
2169
& final_path_pack , & final_path_idx ,
2148
2170
& final_filename );
2149
2171
2150
- my_finalize_packfile (params , status ,
2172
+ my_finalize_packfile (params , status , 1 ,
2151
2173
& temp_path_pack , & temp_path_idx ,
2152
2174
& final_path_pack , & final_path_idx ,
2153
2175
& final_filename );
@@ -2162,6 +2184,56 @@ static void extract_packfile_from_multipack(
2162
2184
strbuf_release (& final_filename );
2163
2185
}
2164
2186
2187
+ struct keep_files_data {
2188
+ timestamp_t max_timestamp ;
2189
+ int pos_of_max ;
2190
+ struct string_list * keep_files ;
2191
+ };
2192
+
2193
+ static void cb_keep_files (const char * full_path , size_t full_path_len ,
2194
+ const char * file_path , void * void_data )
2195
+ {
2196
+ struct keep_files_data * data = void_data ;
2197
+ const char * val ;
2198
+ timestamp_t t ;
2199
+
2200
+ /*
2201
+ * We expect prefetch packfiles named like:
2202
+ *
2203
+ * prefetch-<seconds>-<checksum>.keep
2204
+ */
2205
+ if (!skip_prefix (file_path , "prefetch-" , & val ))
2206
+ return ;
2207
+ if (!ends_with (val , ".keep" ))
2208
+ return ;
2209
+
2210
+ t = strtol (val , NULL , 10 );
2211
+ if (t > data -> max_timestamp ) {
2212
+ data -> pos_of_max = data -> keep_files -> nr ;
2213
+ data -> max_timestamp = t ;
2214
+ }
2215
+
2216
+ string_list_append (data -> keep_files , full_path );
2217
+ }
2218
+
2219
+ static void delete_stale_keep_files (
2220
+ struct gh__request_params * params ,
2221
+ struct gh__response_status * status )
2222
+ {
2223
+ struct string_list keep_files = STRING_LIST_INIT_DUP ;
2224
+ struct keep_files_data data = { 0 , 0 , & keep_files };
2225
+ int k ;
2226
+
2227
+ for_each_file_in_pack_dir (gh__global .buf_odb_path .buf ,
2228
+ cb_keep_files , & data );
2229
+ for (k = 0 ; k < keep_files .nr ; k ++ ) {
2230
+ if (k != data .pos_of_max )
2231
+ unlink (keep_files .items [k ].string );
2232
+ }
2233
+
2234
+ string_list_clear (& keep_files , 0 );
2235
+ }
2236
+
2165
2237
/*
2166
2238
* Cut apart the received multipart response into individual packfiles
2167
2239
* and install each one.
@@ -2180,6 +2252,7 @@ static void install_prefetch(struct gh__request_params *params,
2180
2252
unsigned short np ;
2181
2253
unsigned short k ;
2182
2254
int fd = -1 ;
2255
+ int nr_installed = 0 ;
2183
2256
2184
2257
struct strbuf temp_path_mp = STRBUF_INIT ;
2185
2258
@@ -2220,8 +2293,12 @@ static void install_prefetch(struct gh__request_params *params,
2220
2293
extract_packfile_from_multipack (params , status , fd , k );
2221
2294
if (status -> ec != GH__ERROR_CODE__OK )
2222
2295
break ;
2296
+ nr_installed ++ ;
2223
2297
}
2224
2298
2299
+ if (nr_installed )
2300
+ delete_stale_keep_files (params , status );
2301
+
2225
2302
cleanup :
2226
2303
if (fd != -1 )
2227
2304
close (fd );
0 commit comments