@@ -1882,6 +1882,7 @@ static void my_run_index_pack(struct gh__request_params *params UNUSED,
18821882
18831883static void my_finalize_packfile (struct gh__request_params * params ,
18841884 struct gh__response_status * status ,
1885+ int b_keep ,
18851886 const struct strbuf * temp_path_pack ,
18861887 const struct strbuf * temp_path_idx ,
18871888 struct strbuf * final_path_pack ,
@@ -1901,6 +1902,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
19011902 return ;
19021903 }
19031904
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+
19041920 if (params -> result_list ) {
19051921 struct strbuf result_msg = STRBUF_INIT ;
19061922
@@ -1953,7 +1969,7 @@ static void install_packfile(struct gh__request_params *params,
19531969 create_final_packfile_pathnames ("vfs" , packfile_checksum .buf , NULL ,
19541970 & final_path_pack , & final_path_idx ,
19551971 & final_filename );
1956- my_finalize_packfile (params , status ,
1972+ my_finalize_packfile (params , status , 0 ,
19571973 & temp_path_pack , & temp_path_idx ,
19581974 & final_path_pack , & final_path_idx ,
19591975 & final_filename );
@@ -2049,6 +2065,12 @@ struct ph {
20492065
20502066/*
20512067 * 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.)
20522074 */
20532075static void extract_packfile_from_multipack (
20542076 struct gh__request_params * params ,
@@ -2145,7 +2167,7 @@ static void extract_packfile_from_multipack(
21452167
21462168 } else {
21472169 /*
2148- * Server send the .idx immediately after the .pack in the
2170+ * Server sent the .idx immediately after the .pack in the
21492171 * data stream. I'm tempted to verify it, but that defeats
21502172 * the purpose of having it cached...
21512173 */
@@ -2168,7 +2190,7 @@ static void extract_packfile_from_multipack(
21682190 & final_filename );
21692191 strbuf_release (& buf_timestamp );
21702192
2171- my_finalize_packfile (params , status ,
2193+ my_finalize_packfile (params , status , 1 ,
21722194 & temp_path_pack , & temp_path_idx ,
21732195 & final_path_pack , & final_path_idx ,
21742196 & final_filename );
@@ -2183,6 +2205,56 @@ static void extract_packfile_from_multipack(
21832205 strbuf_release (& final_filename );
21842206}
21852207
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+
21862258/*
21872259 * Cut apart the received multipart response into individual packfiles
21882260 * and install each one.
@@ -2201,6 +2273,7 @@ static void install_prefetch(struct gh__request_params *params,
22012273 unsigned short np ;
22022274 unsigned short k ;
22032275 int fd = -1 ;
2276+ int nr_installed = 0 ;
22042277
22052278 struct strbuf temp_path_mp = STRBUF_INIT ;
22062279
@@ -2245,9 +2318,13 @@ static void install_prefetch(struct gh__request_params *params,
22452318 display_progress (params -> progress , k + 1 );
22462319 if (status -> ec != GH__ERROR_CODE__OK )
22472320 break ;
2321+ nr_installed ++ ;
22482322 }
22492323 stop_progress (& params -> progress );
22502324
2325+ if (nr_installed )
2326+ delete_stale_keep_files (params , status );
2327+
22512328cleanup :
22522329 if (fd != -1 )
22532330 close (fd );
0 commit comments