@@ -74,7 +74,9 @@ static void assign_variant(struct rerere_id *id)
7474
7575 variant = id -> variant ;
7676 if (variant < 0 ) {
77- variant = 0 ; /* for now */
77+ for (variant = 0 ; variant < rr_dir -> status_nr ; variant ++ )
78+ if (!rr_dir -> status [variant ])
79+ break ;
7880 }
7981 fit_variant (rr_dir , variant );
8082 id -> variant = variant ;
@@ -177,15 +179,6 @@ static int has_rerere_resolution(const struct rerere_id *id)
177179 return ((id -> collection -> status [variant ] & both ) == both );
178180}
179181
180- static int has_rerere_preimage (const struct rerere_id * id )
181- {
182- int variant = id -> variant ;
183-
184- if (variant < 0 )
185- return 0 ;
186- return (id -> collection -> status [variant ] & RR_HAS_PREIMAGE );
187- }
188-
189182static struct rerere_id * new_rerere_id_hex (char * hex )
190183{
191184 struct rerere_id * id = xmalloc (sizeof (* id ));
@@ -818,6 +811,13 @@ static void update_paths(struct string_list *update)
818811 rollback_lock_file (& index_lock );
819812}
820813
814+ static void remove_variant (struct rerere_id * id )
815+ {
816+ unlink_or_warn (rerere_path (id , "postimage" ));
817+ unlink_or_warn (rerere_path (id , "preimage" ));
818+ id -> collection -> status [id -> variant ] = 0 ;
819+ }
820+
821821/*
822822 * The path indicated by rr_item may still have conflict for which we
823823 * have a recorded resolution, in which case replay it and optionally
@@ -830,49 +830,71 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
830830{
831831 const char * path = rr_item -> string ;
832832 struct rerere_id * id = rr_item -> util ;
833+ struct rerere_dir * rr_dir = id -> collection ;
833834 int variant ;
834835
835- if (id -> variant < 0 )
836- assign_variant (id );
837836 variant = id -> variant ;
838837
839- if (!has_rerere_preimage (id )) {
838+ /* Has the user resolved it already? */
839+ if (variant >= 0 ) {
840+ if (!handle_file (path , NULL , NULL )) {
841+ copy_file (rerere_path (id , "postimage" ), path , 0666 );
842+ id -> collection -> status [variant ] |= RR_HAS_POSTIMAGE ;
843+ fprintf (stderr , "Recorded resolution for '%s'.\n" , path );
844+ free_rerere_id (rr_item );
845+ rr_item -> util = NULL ;
846+ return ;
847+ }
840848 /*
841- * We are the first to encounter this conflict. Ask
842- * handle_file() to write the normalized contents to
843- * the "preimage" file .
849+ * There may be other variants that can cleanly
850+ * replay. Try them and update the variant number for
851+ * this one .
844852 */
845- handle_file (path , NULL , rerere_path (id , "preimage" ));
846- if (id -> collection -> status [variant ] & RR_HAS_POSTIMAGE ) {
847- const char * path = rerere_path (id , "postimage" );
848- if (unlink (path ))
849- die_errno ("cannot unlink stray '%s'" , path );
850- id -> collection -> status [variant ] &= ~RR_HAS_POSTIMAGE ;
851- }
852- id -> collection -> status [variant ] |= RR_HAS_PREIMAGE ;
853- fprintf (stderr , "Recorded preimage for '%s'\n" , path );
854- return ;
855- } else if (has_rerere_resolution (id )) {
856- /* Is there a recorded resolution we could attempt to apply? */
857- if (merge (id , path ))
858- return ; /* failed to replay */
853+ }
854+
855+ /* Does any existing resolution apply cleanly? */
856+ for (variant = 0 ; variant < rr_dir -> status_nr ; variant ++ ) {
857+ const int both = RR_HAS_PREIMAGE | RR_HAS_POSTIMAGE ;
858+ struct rerere_id vid = * id ;
859+
860+ if ((rr_dir -> status [variant ] & both ) != both )
861+ continue ;
862+
863+ vid .variant = variant ;
864+ if (merge (& vid , path ))
865+ continue ; /* failed to replay */
866+
867+ /*
868+ * If there already is a different variant that applies
869+ * cleanly, there is no point maintaining our own variant.
870+ */
871+ if (0 <= id -> variant && id -> variant != variant )
872+ remove_variant (id );
859873
860874 if (rerere_autoupdate )
861875 string_list_insert (update , path );
862876 else
863877 fprintf (stderr ,
864878 "Resolved '%s' using previous resolution.\n" ,
865879 path );
866- } else if (!handle_file (path , NULL , NULL )) {
867- /* The user has resolved it. */
868- copy_file (rerere_path (id , "postimage" ), path , 0666 );
869- id -> collection -> status [variant ] |= RR_HAS_POSTIMAGE ;
870- fprintf (stderr , "Recorded resolution for '%s'.\n" , path );
871- } else {
880+ free_rerere_id (rr_item );
881+ rr_item -> util = NULL ;
872882 return ;
873883 }
874- free_rerere_id (rr_item );
875- rr_item -> util = NULL ;
884+
885+ /* None of the existing one applies; we need a new variant */
886+ assign_variant (id );
887+
888+ variant = id -> variant ;
889+ handle_file (path , NULL , rerere_path (id , "preimage" ));
890+ if (id -> collection -> status [variant ] & RR_HAS_POSTIMAGE ) {
891+ const char * path = rerere_path (id , "postimage" );
892+ if (unlink (path ))
893+ die_errno ("cannot unlink stray '%s'" , path );
894+ id -> collection -> status [variant ] &= ~RR_HAS_POSTIMAGE ;
895+ }
896+ id -> collection -> status [variant ] |= RR_HAS_PREIMAGE ;
897+ fprintf (stderr , "Recorded preimage for '%s'\n" , path );
876898}
877899
878900static int do_plain_rerere (struct string_list * rr , int fd )
0 commit comments