@@ -30,14 +30,17 @@ static int rerere_dir_alloc;
30
30
#define RR_HAS_PREIMAGE 2
31
31
static struct rerere_dir {
32
32
unsigned char sha1 [20 ];
33
- unsigned char status ;
33
+ int status_alloc , status_nr ;
34
+ unsigned char * status ;
34
35
} * * rerere_dir ;
35
36
36
37
static void free_rerere_dirs (void )
37
38
{
38
39
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 );
40
42
free (rerere_dir [i ]);
43
+ }
41
44
free (rerere_dir );
42
45
rerere_dir_nr = rerere_dir_alloc = 0 ;
43
46
rerere_dir = NULL ;
@@ -53,17 +56,59 @@ static const char *rerere_id_hex(const struct rerere_id *id)
53
56
return sha1_to_hex (id -> collection -> sha1 );
54
57
}
55
58
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
+
56
83
const char * rerere_path (const struct rerere_id * id , const char * file )
57
84
{
58
85
if (!file )
59
86
return git_path ("rr-cache/%s" , rerere_id_hex (id ));
60
87
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 );
62
93
}
63
94
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 )
65
96
{
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 ;
67
112
}
68
113
69
114
static void scan_rerere_dir (struct rerere_dir * rr_dir )
@@ -74,10 +119,15 @@ static void scan_rerere_dir(struct rerere_dir *rr_dir)
74
119
if (!dir )
75
120
return ;
76
121
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
+ }
81
131
}
82
132
closedir (dir );
83
133
}
@@ -100,7 +150,9 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
100
150
if (pos < 0 ) {
101
151
rr_dir = xmalloc (sizeof (* rr_dir ));
102
152
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 ;
104
156
pos = -1 - pos ;
105
157
106
158
/* Make sure the array is big enough ... */
@@ -118,19 +170,27 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
118
170
static int has_rerere_resolution (const struct rerere_id * id )
119
171
{
120
172
const int both = RR_HAS_POSTIMAGE |RR_HAS_PREIMAGE ;
173
+ int variant = id -> variant ;
121
174
122
- return ((id -> collection -> status & both ) == both );
175
+ if (variant < 0 )
176
+ return 0 ;
177
+ return ((id -> collection -> status [variant ] & both ) == both );
123
178
}
124
179
125
180
static int has_rerere_preimage (const struct rerere_id * id )
126
181
{
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 );
128
187
}
129
188
130
189
static struct rerere_id * new_rerere_id_hex (char * hex )
131
190
{
132
191
struct rerere_id * id = xmalloc (sizeof (* id ));
133
192
id -> collection = find_rerere_dir (hex );
193
+ id -> variant = -1 ; /* not known yet */
134
194
return id ;
135
195
}
136
196
@@ -157,16 +217,26 @@ static void read_rr(struct string_list *rr)
157
217
char * path ;
158
218
unsigned char sha1 [20 ];
159
219
struct rerere_id * id ;
220
+ int variant ;
160
221
161
222
/* There has to be the hash, tab, path and then NUL */
162
223
if (buf .len < 42 || get_sha1_hex (buf .buf , sha1 ))
163
224
die ("corrupt MERGE_RR" );
164
225
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' )
166
236
die ("corrupt MERGE_RR" );
167
237
buf .buf [40 ] = '\0' ;
168
- path = buf .buf + 41 ;
169
238
id = new_rerere_id_hex (buf .buf );
239
+ id -> variant = variant ;
170
240
string_list_insert (rr , path )-> util = id ;
171
241
}
172
242
strbuf_release (& buf );
@@ -187,9 +257,16 @@ static int write_rr(struct string_list *rr, int out_fd)
187
257
id = rr -> items [i ].util ;
188
258
if (!id )
189
259
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
+
193
270
if (write_in_full (out_fd , buf .buf , buf .len ) != buf .len )
194
271
die ("unable to write rerere record" );
195
272
@@ -752,7 +829,12 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
752
829
struct string_list * update )
753
830
{
754
831
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 ;
756
838
757
839
if (!has_rerere_preimage (id )) {
758
840
/*
@@ -761,13 +843,13 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
761
843
* the "preimage" file.
762
844
*/
763
845
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 ) {
765
847
const char * path = rerere_path (id , "postimage" );
766
848
if (unlink (path ))
767
849
die_errno ("cannot unlink stray '%s'" , path );
768
- id -> collection -> status &= ~RR_HAS_POSTIMAGE ;
850
+ id -> collection -> status [ variant ] &= ~RR_HAS_POSTIMAGE ;
769
851
}
770
- id -> collection -> status |= RR_HAS_PREIMAGE ;
852
+ id -> collection -> status [ variant ] |= RR_HAS_PREIMAGE ;
771
853
fprintf (stderr , "Recorded preimage for '%s'\n" , path );
772
854
return ;
773
855
} else if (has_rerere_resolution (id )) {
@@ -784,7 +866,7 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
784
866
} else if (!handle_file (path , NULL , NULL )) {
785
867
/* The user has resolved it. */
786
868
copy_file (rerere_path (id , "postimage" ), path , 0666 );
787
- id -> collection -> status |= RR_HAS_POSTIMAGE ;
869
+ id -> collection -> status [ variant ] |= RR_HAS_POSTIMAGE ;
788
870
fprintf (stderr , "Recorded resolution for '%s'.\n" , path );
789
871
} else {
790
872
return ;
@@ -919,6 +1001,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
919
1001
920
1002
/* Nuke the recorded resolution for the conflict */
921
1003
id = new_rerere_id (sha1 );
1004
+ id -> variant = 0 ; /* for now */
922
1005
filename = rerere_path (id , "postimage" );
923
1006
if (unlink (filename ))
924
1007
return (errno == ENOENT
0 commit comments