@@ -1871,6 +1871,7 @@ static void my_run_index_pack(struct gh__request_params *params,
18711871
18721872static void my_finalize_packfile (struct gh__request_params * params ,
18731873 struct gh__response_status * status ,
1874+ int b_keep ,
18741875 const struct strbuf * temp_path_pack ,
18751876 const struct strbuf * temp_path_idx ,
18761877 struct strbuf * final_path_pack ,
@@ -1890,6 +1891,21 @@ static void my_finalize_packfile(struct gh__request_params *params,
18901891 return ;
18911892 }
18921893
1894+ if (b_keep ) {
1895+ struct strbuf keep = STRBUF_INIT ;
1896+ int fd_keep ;
1897+
1898+ strbuf_addbuf (& keep , final_path_pack );
1899+ strbuf_strip_suffix (& keep , ".pack" );
1900+ strbuf_addstr (& keep , ".keep" );
1901+
1902+ fd_keep = xopen (keep .buf , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1903+ if (fd_keep >= 0 )
1904+ close (fd_keep );
1905+
1906+ strbuf_release (& keep );
1907+ }
1908+
18931909 if (params -> result_list ) {
18941910 struct strbuf result_msg = STRBUF_INIT ;
18951911
@@ -1942,7 +1958,7 @@ static void install_packfile(struct gh__request_params *params,
19421958 create_final_packfile_pathnames ("vfs" , packfile_checksum .buf , NULL ,
19431959 & final_path_pack , & final_path_idx ,
19441960 & final_filename );
1945- my_finalize_packfile (params , status ,
1961+ my_finalize_packfile (params , status , 0 ,
19461962 & temp_path_pack , & temp_path_idx ,
19471963 & final_path_pack , & final_path_idx ,
19481964 & final_filename );
@@ -2038,6 +2054,12 @@ struct ph {
20382054
20392055/*
20402056 * Extract the next packfile from the multipack.
2057+ * Install {.pack, .idx, .keep} set.
2058+ *
2059+ * Mark each successfully installed prefetch pack as .keep it as installed
2060+ * in case we have errors decoding/indexing later packs within the received
2061+ * multipart file. (A later pass can delete the unnecessary .keep files
2062+ * from this and any previous invocations.)
20412063 */
20422064static void extract_packfile_from_multipack (
20432065 struct gh__request_params * params ,
@@ -2134,7 +2156,7 @@ static void extract_packfile_from_multipack(
21342156
21352157 } else {
21362158 /*
2137- * Server send the .idx immediately after the .pack in the
2159+ * Server sent the .idx immediately after the .pack in the
21382160 * data stream. I'm tempted to verify it, but that defeats
21392161 * the purpose of having it cached...
21402162 */
@@ -2156,7 +2178,7 @@ static void extract_packfile_from_multipack(
21562178 & final_path_pack , & final_path_idx ,
21572179 & final_filename );
21582180
2159- my_finalize_packfile (params , status ,
2181+ my_finalize_packfile (params , status , 1 ,
21602182 & temp_path_pack , & temp_path_idx ,
21612183 & final_path_pack , & final_path_idx ,
21622184 & final_filename );
@@ -2171,6 +2193,56 @@ static void extract_packfile_from_multipack(
21712193 strbuf_release (& final_filename );
21722194}
21732195
2196+ struct keep_files_data {
2197+ timestamp_t max_timestamp ;
2198+ int pos_of_max ;
2199+ struct string_list * keep_files ;
2200+ };
2201+
2202+ static void cb_keep_files (const char * full_path , size_t full_path_len ,
2203+ const char * file_path , void * void_data )
2204+ {
2205+ struct keep_files_data * data = void_data ;
2206+ const char * val ;
2207+ timestamp_t t ;
2208+
2209+ /*
2210+ * We expect prefetch packfiles named like:
2211+ *
2212+ * prefetch-<seconds>-<checksum>.keep
2213+ */
2214+ if (!skip_prefix (file_path , "prefetch-" , & val ))
2215+ return ;
2216+ if (!ends_with (val , ".keep" ))
2217+ return ;
2218+
2219+ t = strtol (val , NULL , 10 );
2220+ if (t > data -> max_timestamp ) {
2221+ data -> pos_of_max = data -> keep_files -> nr ;
2222+ data -> max_timestamp = t ;
2223+ }
2224+
2225+ string_list_append (data -> keep_files , full_path );
2226+ }
2227+
2228+ static void delete_stale_keep_files (
2229+ struct gh__request_params * params ,
2230+ struct gh__response_status * status )
2231+ {
2232+ struct string_list keep_files = STRING_LIST_INIT_DUP ;
2233+ struct keep_files_data data = { 0 , 0 , & keep_files };
2234+ int k ;
2235+
2236+ for_each_file_in_pack_dir (gh__global .buf_odb_path .buf ,
2237+ cb_keep_files , & data );
2238+ for (k = 0 ; k < keep_files .nr ; k ++ ) {
2239+ if (k != data .pos_of_max )
2240+ unlink (keep_files .items [k ].string );
2241+ }
2242+
2243+ string_list_clear (& keep_files , 0 );
2244+ }
2245+
21742246/*
21752247 * Cut apart the received multipart response into individual packfiles
21762248 * and install each one.
@@ -2189,6 +2261,7 @@ static void install_prefetch(struct gh__request_params *params,
21892261 unsigned short np ;
21902262 unsigned short k ;
21912263 int fd = -1 ;
2264+ int nr_installed = 0 ;
21922265
21932266 struct strbuf temp_path_mp = STRBUF_INIT ;
21942267
@@ -2229,8 +2302,12 @@ static void install_prefetch(struct gh__request_params *params,
22292302 extract_packfile_from_multipack (params , status , fd , k );
22302303 if (status -> ec != GH__ERROR_CODE__OK )
22312304 break ;
2305+ nr_installed ++ ;
22322306 }
22332307
2308+ if (nr_installed )
2309+ delete_stale_keep_files (params , status );
2310+
22342311cleanup :
22352312 if (fd != -1 )
22362313 close (fd );
0 commit comments