@@ -22,17 +22,43 @@ static int rerere_autoupdate;
2222
2323static char * merge_rr_path ;
2424
25- const char * rerere_path ( const char * id , const char * file )
25+ static void free_rerere_id ( struct string_list_item * item )
2626{
27- return git_path ("rr-cache/%s/%s" , id , file );
27+ free (item -> util );
28+ }
29+
30+ static const char * rerere_id_hex (const struct rerere_id * id )
31+ {
32+ return id -> hex ;
33+ }
34+
35+ const char * rerere_path (const struct rerere_id * id , const char * file )
36+ {
37+ if (!file )
38+ return git_path ("rr-cache/%s" , rerere_id_hex (id ));
39+
40+ return git_path ("rr-cache/%s/%s" , rerere_id_hex (id ), file );
2841}
2942
30- static int has_rerere_resolution (const char * id )
43+ static int has_rerere_resolution (const struct rerere_id * id )
3144{
3245 struct stat st ;
46+
3347 return !stat (rerere_path (id , "postimage" ), & st );
3448}
3549
50+ static struct rerere_id * new_rerere_id_hex (char * hex )
51+ {
52+ struct rerere_id * id = xmalloc (sizeof (* id ));
53+ strcpy (id -> hex , hex );
54+ return id ;
55+ }
56+
57+ static struct rerere_id * new_rerere_id (unsigned char * sha1 )
58+ {
59+ return new_rerere_id_hex (sha1_to_hex (sha1 ));
60+ }
61+
3662/*
3763 * $GIT_DIR/MERGE_RR file is a collection of records, each of which is
3864 * "conflict ID", a HT and pathname, terminated with a NUL, and is
@@ -50,6 +76,7 @@ static void read_rr(struct string_list *rr)
5076 while (!strbuf_getwholeline (& buf , in , '\0' )) {
5177 char * path ;
5278 unsigned char sha1 [20 ];
79+ struct rerere_id * id ;
5380
5481 /* There has to be the hash, tab, path and then NUL */
5582 if (buf .len < 42 || get_sha1_hex (buf .buf , sha1 ))
@@ -59,8 +86,8 @@ static void read_rr(struct string_list *rr)
5986 die ("corrupt MERGE_RR" );
6087 buf .buf [40 ] = '\0' ;
6188 path = buf .buf + 41 ;
62-
63- string_list_insert (rr , path )-> util = xstrdup ( buf . buf ) ;
89+ id = new_rerere_id_hex ( buf . buf );
90+ string_list_insert (rr , path )-> util = id ;
6491 }
6592 strbuf_release (& buf );
6693 fclose (in );
@@ -73,12 +100,15 @@ static int write_rr(struct string_list *rr, int out_fd)
73100 int i ;
74101 for (i = 0 ; i < rr -> nr ; i ++ ) {
75102 struct strbuf buf = STRBUF_INIT ;
103+ struct rerere_id * id ;
76104
77105 assert (rr -> items [i ].util != RERERE_RESOLVED );
78- if (!rr -> items [i ].util )
106+
107+ id = rr -> items [i ].util ;
108+ if (!id )
79109 continue ;
80110 strbuf_addf (& buf , "%s\t%s%c" ,
81- ( char * ) rr -> items [ i ]. util ,
111+ rerere_id_hex ( id ) ,
82112 rr -> items [i ].string , 0 );
83113 if (write_in_full (out_fd , buf .buf , buf .len ) != buf .len )
84114 die ("unable to write rerere record" );
@@ -530,7 +560,7 @@ int rerere_remaining(struct string_list *merge_rr)
530560 struct string_list_item * it ;
531561 it = string_list_lookup (merge_rr , (const char * )e -> name );
532562 if (it != NULL ) {
533- free (it -> util );
563+ free_rerere_id (it );
534564 it -> util = RERERE_RESOLVED ;
535565 }
536566 }
@@ -548,7 +578,7 @@ int rerere_remaining(struct string_list *merge_rr)
548578 * Returns 0 for successful replay of recorded resolution, or non-zero
549579 * for failure.
550580 */
551- static int merge (const char * id , const char * path )
581+ static int merge (const struct rerere_id * id , const char * path )
552582{
553583 int ret ;
554584 mmfile_t cur = {NULL , 0 }, base = {NULL , 0 }, other = {NULL , 0 };
@@ -582,8 +612,8 @@ static int merge(const char *id, const char *path)
582612 */
583613 if (utime (rerere_path (id , "postimage" ), NULL ) < 0 )
584614 warning ("failed utime() on %s: %s" ,
585- rerere_path (id , "postimage" ),
586- strerror (errno ));
615+ rerere_path (id , "postimage" ),
616+ strerror (errno ));
587617
588618 /* Update "path" with the resolution */
589619 f = fopen (path , "w" );
@@ -640,7 +670,7 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
640670 struct string_list * update )
641671{
642672 const char * path = rr_item -> string ;
643- const char * id = ( const char * ) rr_item -> util ;
673+ const struct rerere_id * id = rr_item -> util ;
644674
645675 /* Is there a recorded resolution we could attempt to apply? */
646676 if (has_rerere_resolution (id )) {
@@ -660,7 +690,7 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
660690 } else {
661691 return ;
662692 }
663- free (rr_item -> util );
693+ free_rerere_id (rr_item );
664694 rr_item -> util = NULL ;
665695}
666696
@@ -679,10 +709,10 @@ static int do_plain_rerere(struct string_list *rr, int fd)
679709 * initial run would catch all and register their preimages.
680710 */
681711 for (i = 0 ; i < conflict .nr ; i ++ ) {
712+ struct rerere_id * id ;
682713 unsigned char sha1 [20 ];
683- char * id ;
684- int ret ;
685714 const char * path = conflict .items [i ].string ;
715+ int ret ;
686716
687717 if (string_list_has_string (rr , path ))
688718 continue ;
@@ -695,7 +725,8 @@ static int do_plain_rerere(struct string_list *rr, int fd)
695725 ret = handle_file (path , sha1 , NULL );
696726 if (ret < 1 )
697727 continue ;
698- id = xstrdup (sha1_to_hex (sha1 ));
728+
729+ id = new_rerere_id (sha1 );
699730 string_list_insert (rr , path )-> util = id ;
700731
701732 /*
@@ -706,7 +737,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
706737 * NEEDSWORK: make sure "gc" does not remove
707738 * preimage without removing the directory.
708739 */
709- if (mkdir_in_gitdir (git_path ( "rr-cache/%s" , id )))
740+ if (mkdir_in_gitdir (rerere_path ( id , NULL )))
710741 continue ;
711742
712743 /*
@@ -788,7 +819,7 @@ int rerere(int flags)
788819static int rerere_forget_one_path (const char * path , struct string_list * rr )
789820{
790821 const char * filename ;
791- char * id ;
822+ struct rerere_id * id ;
792823 unsigned char sha1 [20 ];
793824 int ret ;
794825 struct string_list_item * item ;
@@ -802,7 +833,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
802833 return error ("Could not parse conflict hunks in '%s'" , path );
803834
804835 /* Nuke the recorded resolution for the conflict */
805- id = xstrdup ( sha1_to_hex ( sha1 ) );
836+ id = new_rerere_id ( sha1 );
806837 filename = rerere_path (id , "postimage" );
807838 if (unlink (filename ))
808839 return (errno == ENOENT
@@ -822,7 +853,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
822853 * conflict when the user is done.
823854 */
824855 item = string_list_insert (rr , path );
825- free (item -> util );
856+ free_rerere_id (item );
826857 item -> util = id ;
827858 fprintf (stderr , "Forgot resolution for %s\n" , path );
828859 return 0 ;
@@ -859,22 +890,38 @@ int rerere_forget(struct pathspec *pathspec)
859890/*
860891 * Garbage collection support
861892 */
862- static time_t rerere_created_at (const char * id )
893+
894+ /*
895+ * Note that this is not reentrant but is used only one-at-a-time
896+ * so it does not matter right now.
897+ */
898+ static struct rerere_id * dirname_to_id (const char * name )
899+ {
900+ static struct rerere_id id ;
901+ strcpy (id .hex , name );
902+ return & id ;
903+ }
904+
905+ static time_t rerere_created_at (const char * dir_name )
863906{
864907 struct stat st ;
908+ struct rerere_id * id = dirname_to_id (dir_name );
909+
865910 return stat (rerere_path (id , "preimage" ), & st ) ? (time_t ) 0 : st .st_mtime ;
866911}
867912
868- static time_t rerere_last_used_at (const char * id )
913+ static time_t rerere_last_used_at (const char * dir_name )
869914{
870915 struct stat st ;
916+ struct rerere_id * id = dirname_to_id (dir_name );
917+
871918 return stat (rerere_path (id , "postimage" ), & st ) ? (time_t ) 0 : st .st_mtime ;
872919}
873920
874921/*
875922 * Remove the recorded resolution for a given conflict ID
876923 */
877- static void unlink_rr_item (const char * id )
924+ static void unlink_rr_item (struct rerere_id * id )
878925{
879926 unlink (rerere_path (id , "thisimage" ));
880927 unlink (rerere_path (id , "preimage" ));
@@ -884,7 +931,7 @@ static void unlink_rr_item(const char *id)
884931 * assume that we already have preimage recorded in
885932 * do_plain_rerere()?
886933 */
887- rmdir (git_path ( "rr-cache/%s" , id ));
934+ rmdir (rerere_path ( id , NULL ));
888935}
889936
890937void rerere_gc (struct string_list * rr )
@@ -923,7 +970,7 @@ void rerere_gc(struct string_list *rr)
923970 closedir (dir );
924971 /* ... and then remove them one-by-one */
925972 for (i = 0 ; i < to_remove .nr ; i ++ )
926- unlink_rr_item (to_remove .items [i ].string );
973+ unlink_rr_item (dirname_to_id ( to_remove .items [i ].string ) );
927974 string_list_clear (& to_remove , 0 );
928975}
929976
@@ -939,7 +986,7 @@ void rerere_clear(struct string_list *merge_rr)
939986 int i ;
940987
941988 for (i = 0 ; i < merge_rr -> nr ; i ++ ) {
942- const char * id = ( const char * ) merge_rr -> items [i ].util ;
989+ struct rerere_id * id = merge_rr -> items [i ].util ;
943990 if (!has_rerere_resolution (id ))
944991 unlink_rr_item (id );
945992 }
0 commit comments