@@ -1890,6 +1890,7 @@ static void my_run_index_pack(struct gh__request_params *params UNUSED,
18901890
18911891static void my_finalize_packfile (struct gh__request_params * params ,
18921892 struct gh__response_status * status ,
1893+ int b_keep ,
18931894 const struct strbuf * temp_path_pack ,
18941895 const struct strbuf * temp_path_idx ,
18951896 struct strbuf * final_path_pack ,
@@ -1909,6 +1910,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
19091910 return ;
19101911 }
19111912
1913+ if (b_keep ) {
1914+ struct strbuf keep = STRBUF_INIT ;
1915+ int fd_keep ;
1916+
1917+ strbuf_addbuf (& keep , final_path_pack );
1918+ strbuf_strip_suffix (& keep , ".pack" );
1919+ strbuf_addstr (& keep , ".keep" );
1920+
1921+ fd_keep = xopen (keep .buf , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1922+ if (fd_keep >= 0 )
1923+ close (fd_keep );
1924+
1925+ strbuf_release (& keep );
1926+ }
1927+
19121928 if (params -> result_list ) {
19131929 struct strbuf result_msg = STRBUF_INIT ;
19141930
@@ -1961,7 +1977,7 @@ static void install_packfile(struct gh__request_params *params,
19611977 create_final_packfile_pathnames ("vfs" , packfile_checksum .buf , NULL ,
19621978 & final_path_pack , & final_path_idx ,
19631979 & final_filename );
1964- my_finalize_packfile (params , status ,
1980+ my_finalize_packfile (params , status , 0 ,
19651981 & temp_path_pack , & temp_path_idx ,
19661982 & final_path_pack , & final_path_idx ,
19671983 & final_filename );
@@ -2057,6 +2073,12 @@ struct ph {
20572073
20582074/*
20592075 * Extract the next packfile from the multipack.
2076+ * Install {.pack, .idx, .keep} set.
2077+ *
2078+ * Mark each successfully installed prefetch pack as .keep it as installed
2079+ * in case we have errors decoding/indexing later packs within the received
2080+ * multipart file. (A later pass can delete the unnecessary .keep files
2081+ * from this and any previous invocations.)
20602082 */
20612083static void extract_packfile_from_multipack (
20622084 struct gh__request_params * params ,
@@ -2153,7 +2175,7 @@ static void extract_packfile_from_multipack(
21532175
21542176 } else {
21552177 /*
2156- * Server send the .idx immediately after the .pack in the
2178+ * Server sent the .idx immediately after the .pack in the
21572179 * data stream. I'm tempted to verify it, but that defeats
21582180 * the purpose of having it cached...
21592181 */
@@ -2176,7 +2198,7 @@ static void extract_packfile_from_multipack(
21762198 & final_filename );
21772199 strbuf_release (& buf_timestamp );
21782200
2179- my_finalize_packfile (params , status ,
2201+ my_finalize_packfile (params , status , 1 ,
21802202 & temp_path_pack , & temp_path_idx ,
21812203 & final_path_pack , & final_path_idx ,
21822204 & final_filename );
@@ -2191,6 +2213,56 @@ static void extract_packfile_from_multipack(
21912213 strbuf_release (& final_filename );
21922214}
21932215
2216+ struct keep_files_data {
2217+ timestamp_t max_timestamp ;
2218+ int pos_of_max ;
2219+ struct string_list * keep_files ;
2220+ };
2221+
2222+ static void cb_keep_files (const char * full_path , size_t full_path_len UNUSED ,
2223+ const char * file_path , void * void_data )
2224+ {
2225+ struct keep_files_data * data = void_data ;
2226+ const char * val ;
2227+ timestamp_t t ;
2228+
2229+ /*
2230+ * We expect prefetch packfiles named like:
2231+ *
2232+ * prefetch-<seconds>-<checksum>.keep
2233+ */
2234+ if (!skip_prefix (file_path , "prefetch-" , & val ))
2235+ return ;
2236+ if (!ends_with (val , ".keep" ))
2237+ return ;
2238+
2239+ t = strtol (val , NULL , 10 );
2240+ if (t > data -> max_timestamp ) {
2241+ data -> pos_of_max = data -> keep_files -> nr ;
2242+ data -> max_timestamp = t ;
2243+ }
2244+
2245+ string_list_append (data -> keep_files , full_path );
2246+ }
2247+
2248+ static void delete_stale_keep_files (
2249+ struct gh__request_params * params UNUSED ,
2250+ struct gh__response_status * status UNUSED )
2251+ {
2252+ struct string_list keep_files = STRING_LIST_INIT_DUP ;
2253+ struct keep_files_data data = { 0 , 0 , & keep_files };
2254+ size_t k ;
2255+
2256+ for_each_file_in_pack_dir (gh__global .buf_odb_path .buf ,
2257+ cb_keep_files , & data );
2258+ for (k = 0 ; k < keep_files .nr ; k ++ ) {
2259+ if ((ssize_t )k != data .pos_of_max )
2260+ unlink (keep_files .items [k ].string );
2261+ }
2262+
2263+ string_list_clear (& keep_files , 0 );
2264+ }
2265+
21942266/*
21952267 * Cut apart the received multipart response into individual packfiles
21962268 * and install each one.
@@ -2209,6 +2281,7 @@ static void install_prefetch(struct gh__request_params *params,
22092281 unsigned short np ;
22102282 unsigned short k ;
22112283 int fd = -1 ;
2284+ int nr_installed = 0 ;
22122285
22132286 struct strbuf temp_path_mp = STRBUF_INIT ;
22142287
@@ -2253,9 +2326,13 @@ static void install_prefetch(struct gh__request_params *params,
22532326 display_progress (params -> progress , k + 1 );
22542327 if (status -> ec != GH__ERROR_CODE__OK )
22552328 break ;
2329+ nr_installed ++ ;
22562330 }
22572331 stop_progress (& params -> progress );
22582332
2333+ if (nr_installed )
2334+ delete_stale_keep_files (params , status );
2335+
22592336cleanup :
22602337 if (fd != -1 )
22612338 close (fd );
0 commit comments