@@ -1081,29 +1081,16 @@ int rerere_forget(struct pathspec *pathspec)
10811081 * Garbage collection support
10821082 */
10831083
1084- /*
1085- * Note that this is not reentrant but is used only one-at-a-time
1086- * so it does not matter right now.
1087- */
1088- static struct rerere_id * dirname_to_id (const char * name )
1089- {
1090- static struct rerere_id id ;
1091- id .collection = find_rerere_dir (name );
1092- return & id ;
1093- }
1094-
1095- static time_t rerere_created_at (const char * dir_name )
1084+ static time_t rerere_created_at (struct rerere_id * id )
10961085{
10971086 struct stat st ;
1098- struct rerere_id * id = dirname_to_id (dir_name );
10991087
11001088 return stat (rerere_path (id , "preimage" ), & st ) ? (time_t ) 0 : st .st_mtime ;
11011089}
11021090
1103- static time_t rerere_last_used_at (const char * dir_name )
1091+ static time_t rerere_last_used_at (struct rerere_id * id )
11041092{
11051093 struct stat st ;
1106- struct rerere_id * id = dirname_to_id (dir_name );
11071094
11081095 return stat (rerere_path (id , "postimage" ), & st ) ? (time_t ) 0 : st .st_mtime ;
11091096}
@@ -1113,24 +1100,37 @@ static time_t rerere_last_used_at(const char *dir_name)
11131100 */
11141101static void unlink_rr_item (struct rerere_id * id )
11151102{
1116- unlink (rerere_path (id , "thisimage" ));
1117- unlink (rerere_path (id , "preimage" ));
1118- unlink (rerere_path (id , "postimage" ));
1119- /*
1120- * NEEDSWORK: what if this rmdir() fails? Wouldn't we then
1121- * assume that we already have preimage recorded in
1122- * do_plain_rerere()?
1123- */
1124- rmdir (rerere_path (id , NULL ));
1103+ unlink_or_warn (rerere_path (id , "thisimage" ));
1104+ remove_variant (id );
1105+ id -> collection -> status [id -> variant ] = 0 ;
1106+ }
1107+
1108+ static void prune_one (struct rerere_id * id , time_t now ,
1109+ int cutoff_resolve , int cutoff_noresolve )
1110+ {
1111+ time_t then ;
1112+ int cutoff ;
1113+
1114+ then = rerere_last_used_at (id );
1115+ if (then )
1116+ cutoff = cutoff_resolve ;
1117+ else {
1118+ then = rerere_created_at (id );
1119+ if (!then )
1120+ return ;
1121+ cutoff = cutoff_noresolve ;
1122+ }
1123+ if (then < now - cutoff * 86400 )
1124+ unlink_rr_item (id );
11251125}
11261126
11271127void rerere_gc (struct string_list * rr )
11281128{
11291129 struct string_list to_remove = STRING_LIST_INIT_DUP ;
11301130 DIR * dir ;
11311131 struct dirent * e ;
1132- int i , cutoff ;
1133- time_t now = time (NULL ), then ;
1132+ int i ;
1133+ time_t now = time (NULL );
11341134 int cutoff_noresolve = 15 ;
11351135 int cutoff_resolve = 60 ;
11361136
@@ -1142,25 +1142,32 @@ void rerere_gc(struct string_list *rr)
11421142 die_errno ("unable to open rr-cache directory" );
11431143 /* Collect stale conflict IDs ... */
11441144 while ((e = readdir (dir ))) {
1145+ struct rerere_dir * rr_dir ;
1146+ struct rerere_id id ;
1147+ int now_empty ;
1148+
11451149 if (is_dot_or_dotdot (e -> d_name ))
11461150 continue ;
1147-
1148- then = rerere_last_used_at (e -> d_name );
1149- if (then ) {
1150- cutoff = cutoff_resolve ;
1151- } else {
1152- then = rerere_created_at (e -> d_name );
1153- if (!then )
1154- continue ;
1155- cutoff = cutoff_noresolve ;
1151+ rr_dir = find_rerere_dir (e -> d_name );
1152+ if (!rr_dir )
1153+ continue ; /* or should we remove e->d_name? */
1154+
1155+ now_empty = 1 ;
1156+ for (id .variant = 0 , id .collection = rr_dir ;
1157+ id .variant < id .collection -> status_nr ;
1158+ id .variant ++ ) {
1159+ prune_one (& id , now , cutoff_resolve , cutoff_noresolve );
1160+ if (id .collection -> status [id .variant ])
1161+ now_empty = 0 ;
11561162 }
1157- if (then < now - cutoff * 86400 )
1163+ if (now_empty )
11581164 string_list_append (& to_remove , e -> d_name );
11591165 }
11601166 closedir (dir );
1161- /* ... and then remove them one-by-one */
1167+
1168+ /* ... and then remove the empty directories */
11621169 for (i = 0 ; i < to_remove .nr ; i ++ )
1163- unlink_rr_item ( dirname_to_id ( to_remove .items [i ].string ));
1170+ rmdir ( git_path ( "rr-cache/%s" , to_remove .items [i ].string ));
11641171 string_list_clear (& to_remove , 0 );
11651172}
11661173
@@ -1177,8 +1184,10 @@ void rerere_clear(struct string_list *merge_rr)
11771184
11781185 for (i = 0 ; i < merge_rr -> nr ; i ++ ) {
11791186 struct rerere_id * id = merge_rr -> items [i ].util ;
1180- if (!has_rerere_resolution (id ))
1187+ if (!has_rerere_resolution (id )) {
11811188 unlink_rr_item (id );
1189+ rmdir (rerere_path (id , NULL ));
1190+ }
11821191 }
11831192 unlink_or_warn (git_path ("MERGE_RR" ));
11841193}
0 commit comments