@@ -30,14 +30,17 @@ static int rerere_dir_alloc;
3030#define RR_HAS_PREIMAGE 2
3131static struct rerere_dir {
3232 unsigned char sha1 [20 ];
33- unsigned char status ;
33+ int status_alloc , status_nr ;
34+ unsigned char * status ;
3435} * * rerere_dir ;
3536
3637static void free_rerere_dirs (void )
3738{
3839 int i ;
39- for (i = 0 ; i < rerere_dir_nr ; i ++ )
40+ for (i = 0 ; i < rerere_dir_nr ; i ++ ) {
41+ free (rerere_dir [i ]-> status );
4042 free (rerere_dir [i ]);
43+ }
4144 free (rerere_dir );
4245 rerere_dir_nr = rerere_dir_alloc = 0 ;
4346 rerere_dir = NULL ;
@@ -53,17 +56,59 @@ static const char *rerere_id_hex(const struct rerere_id *id)
5356 return sha1_to_hex (id -> collection -> sha1 );
5457}
5558
59+ static void fit_variant (struct rerere_dir * rr_dir , int variant )
60+ {
61+ variant ++ ;
62+ ALLOC_GROW (rr_dir -> status , variant , rr_dir -> status_alloc );
63+ if (rr_dir -> status_nr < variant ) {
64+ memset (rr_dir -> status + rr_dir -> status_nr ,
65+ '\0' , variant - rr_dir -> status_nr );
66+ rr_dir -> status_nr = variant ;
67+ }
68+ }
69+
70+ static void assign_variant (struct rerere_id * id )
71+ {
72+ int variant ;
73+ struct rerere_dir * rr_dir = id -> collection ;
74+
75+ variant = id -> variant ;
76+ if (variant < 0 ) {
77+ variant = 0 ; /* for now */
78+ }
79+ fit_variant (rr_dir , variant );
80+ id -> variant = variant ;
81+ }
82+
5683const char * rerere_path (const struct rerere_id * id , const char * file )
5784{
5885 if (!file )
5986 return git_path ("rr-cache/%s" , rerere_id_hex (id ));
6087
61- return git_path ("rr-cache/%s/%s" , rerere_id_hex (id ), file );
88+ if (id -> variant <= 0 )
89+ return git_path ("rr-cache/%s/%s" , rerere_id_hex (id ), file );
90+
91+ return git_path ("rr-cache/%s/%s.%d" ,
92+ rerere_id_hex (id ), file , id -> variant );
6293}
6394
64- static int is_rr_file (const char * name , const char * filename )
95+ static int is_rr_file (const char * name , const char * filename , int * variant )
6596{
66- return !strcmp (name , filename );
97+ const char * suffix ;
98+ char * ep ;
99+
100+ if (!strcmp (name , filename )) {
101+ * variant = 0 ;
102+ return 1 ;
103+ }
104+ if (!skip_prefix (name , filename , & suffix ) || * suffix != '.' )
105+ return 0 ;
106+
107+ errno = 0 ;
108+ * variant = strtol (suffix + 1 , & ep , 10 );
109+ if (errno || * ep )
110+ return 0 ;
111+ return 1 ;
67112}
68113
69114static void scan_rerere_dir (struct rerere_dir * rr_dir )
@@ -74,10 +119,15 @@ static void scan_rerere_dir(struct rerere_dir *rr_dir)
74119 if (!dir )
75120 return ;
76121 while ((de = readdir (dir )) != NULL ) {
77- if (is_rr_file (de -> d_name , "postimage" ))
78- rr_dir -> status |= RR_HAS_POSTIMAGE ;
79- else if (is_rr_file (de -> d_name , "preimage" ))
80- rr_dir -> status |= RR_HAS_PREIMAGE ;
122+ int variant ;
123+
124+ if (is_rr_file (de -> d_name , "postimage" , & variant )) {
125+ fit_variant (rr_dir , variant );
126+ rr_dir -> status [variant ] |= RR_HAS_POSTIMAGE ;
127+ } else if (is_rr_file (de -> d_name , "preimage" , & variant )) {
128+ fit_variant (rr_dir , variant );
129+ rr_dir -> status [variant ] |= RR_HAS_PREIMAGE ;
130+ }
81131 }
82132 closedir (dir );
83133}
@@ -100,7 +150,9 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
100150 if (pos < 0 ) {
101151 rr_dir = xmalloc (sizeof (* rr_dir ));
102152 hashcpy (rr_dir -> sha1 , sha1 );
103- rr_dir -> status = 0 ;
153+ rr_dir -> status = NULL ;
154+ rr_dir -> status_nr = 0 ;
155+ rr_dir -> status_alloc = 0 ;
104156 pos = -1 - pos ;
105157
106158 /* Make sure the array is big enough ... */
@@ -118,19 +170,27 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
118170static int has_rerere_resolution (const struct rerere_id * id )
119171{
120172 const int both = RR_HAS_POSTIMAGE |RR_HAS_PREIMAGE ;
173+ int variant = id -> variant ;
121174
122- return ((id -> collection -> status & both ) == both );
175+ if (variant < 0 )
176+ return 0 ;
177+ return ((id -> collection -> status [variant ] & both ) == both );
123178}
124179
125180static int has_rerere_preimage (const struct rerere_id * id )
126181{
127- return (id -> collection -> status & RR_HAS_PREIMAGE );
182+ int variant = id -> variant ;
183+
184+ if (variant < 0 )
185+ return 0 ;
186+ return (id -> collection -> status [variant ] & RR_HAS_PREIMAGE );
128187}
129188
130189static struct rerere_id * new_rerere_id_hex (char * hex )
131190{
132191 struct rerere_id * id = xmalloc (sizeof (* id ));
133192 id -> collection = find_rerere_dir (hex );
193+ id -> variant = -1 ; /* not known yet */
134194 return id ;
135195}
136196
@@ -157,16 +217,26 @@ static void read_rr(struct string_list *rr)
157217 char * path ;
158218 unsigned char sha1 [20 ];
159219 struct rerere_id * id ;
220+ int variant ;
160221
161222 /* There has to be the hash, tab, path and then NUL */
162223 if (buf .len < 42 || get_sha1_hex (buf .buf , sha1 ))
163224 die ("corrupt MERGE_RR" );
164225
165- if (buf .buf [40 ] != '\t' )
226+ if (buf .buf [40 ] != '.' ) {
227+ variant = 0 ;
228+ path = buf .buf + 40 ;
229+ } else {
230+ errno = 0 ;
231+ variant = strtol (buf .buf + 41 , & path , 10 );
232+ if (errno )
233+ die ("corrupt MERGE_RR" );
234+ }
235+ if (* (path ++ ) != '\t' )
166236 die ("corrupt MERGE_RR" );
167237 buf .buf [40 ] = '\0' ;
168- path = buf .buf + 41 ;
169238 id = new_rerere_id_hex (buf .buf );
239+ id -> variant = variant ;
170240 string_list_insert (rr , path )-> util = id ;
171241 }
172242 strbuf_release (& buf );
@@ -187,9 +257,16 @@ static int write_rr(struct string_list *rr, int out_fd)
187257 id = rr -> items [i ].util ;
188258 if (!id )
189259 continue ;
190- strbuf_addf (& buf , "%s\t%s%c" ,
191- rerere_id_hex (id ),
192- rr -> items [i ].string , 0 );
260+ assert (id -> variant >= 0 );
261+ if (0 < id -> variant )
262+ strbuf_addf (& buf , "%s.%d\t%s%c" ,
263+ rerere_id_hex (id ), id -> variant ,
264+ rr -> items [i ].string , 0 );
265+ else
266+ strbuf_addf (& buf , "%s\t%s%c" ,
267+ rerere_id_hex (id ),
268+ rr -> items [i ].string , 0 );
269+
193270 if (write_in_full (out_fd , buf .buf , buf .len ) != buf .len )
194271 die ("unable to write rerere record" );
195272
@@ -752,7 +829,12 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
752829 struct string_list * update )
753830{
754831 const char * path = rr_item -> string ;
755- const struct rerere_id * id = rr_item -> util ;
832+ struct rerere_id * id = rr_item -> util ;
833+ int variant ;
834+
835+ if (id -> variant < 0 )
836+ assign_variant (id );
837+ variant = id -> variant ;
756838
757839 if (!has_rerere_preimage (id )) {
758840 /*
@@ -761,13 +843,13 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
761843 * the "preimage" file.
762844 */
763845 handle_file (path , NULL , rerere_path (id , "preimage" ));
764- if (id -> collection -> status & RR_HAS_POSTIMAGE ) {
846+ if (id -> collection -> status [ variant ] & RR_HAS_POSTIMAGE ) {
765847 const char * path = rerere_path (id , "postimage" );
766848 if (unlink (path ))
767849 die_errno ("cannot unlink stray '%s'" , path );
768- id -> collection -> status &= ~RR_HAS_POSTIMAGE ;
850+ id -> collection -> status [ variant ] &= ~RR_HAS_POSTIMAGE ;
769851 }
770- id -> collection -> status |= RR_HAS_PREIMAGE ;
852+ id -> collection -> status [ variant ] |= RR_HAS_PREIMAGE ;
771853 fprintf (stderr , "Recorded preimage for '%s'\n" , path );
772854 return ;
773855 } else if (has_rerere_resolution (id )) {
@@ -784,7 +866,7 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
784866 } else if (!handle_file (path , NULL , NULL )) {
785867 /* The user has resolved it. */
786868 copy_file (rerere_path (id , "postimage" ), path , 0666 );
787- id -> collection -> status |= RR_HAS_POSTIMAGE ;
869+ id -> collection -> status [ variant ] |= RR_HAS_POSTIMAGE ;
788870 fprintf (stderr , "Recorded resolution for '%s'.\n" , path );
789871 } else {
790872 return ;
@@ -919,6 +1001,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
9191001
9201002 /* Nuke the recorded resolution for the conflict */
9211003 id = new_rerere_id (sha1 );
1004+ id -> variant = 0 ; /* for now */
9221005 filename = rerere_path (id , "postimage" );
9231006 if (unlink (filename ))
9241007 return (errno == ENOENT
0 commit comments