@@ -34,6 +34,20 @@ enum ws_ignore {
3434 ignore_ws_change
3535};
3636
37+ /*
38+ * We need to keep track of how symlinks in the preimage are
39+ * manipulated by the patches. A patch to add a/b/c where a/b
40+ * is a symlink should not be allowed to affect the directory
41+ * the symlink points at, but if the same patch removes a/b,
42+ * it is perfectly fine, as the patch removes a/b to make room
43+ * to create a directory a/b so that a/b/c can be created.
44+ *
45+ * See also "struct string_list symlink_changes" in "struct
46+ * apply_state".
47+ */
48+ #define SYMLINK_GOES_AWAY 01
49+ #define SYMLINK_IN_RESULT 02
50+
3751struct apply_state {
3852 const char * prefix ;
3953 int prefix_length ;
@@ -75,6 +89,7 @@ struct apply_state {
7589
7690 /* Various "current state" */
7791 int linenr ; /* current line number */
92+ struct string_list symlink_changes ; /* we have to track symlinks */
7893
7994 /*
8095 * For "diff-stat" like behaviour, we keep track of the biggest change
@@ -3702,52 +3717,42 @@ static int check_to_create(struct apply_state *state,
37023717 return 0 ;
37033718}
37043719
3705- /*
3706- * We need to keep track of how symlinks in the preimage are
3707- * manipulated by the patches. A patch to add a/b/c where a/b
3708- * is a symlink should not be allowed to affect the directory
3709- * the symlink points at, but if the same patch removes a/b,
3710- * it is perfectly fine, as the patch removes a/b to make room
3711- * to create a directory a/b so that a/b/c can be created.
3712- */
3713- static struct string_list symlink_changes ;
3714- #define SYMLINK_GOES_AWAY 01
3715- #define SYMLINK_IN_RESULT 02
3716-
3717- static uintptr_t register_symlink_changes (const char * path , uintptr_t what )
3720+ static uintptr_t register_symlink_changes (struct apply_state * state ,
3721+ const char * path ,
3722+ uintptr_t what )
37183723{
37193724 struct string_list_item * ent ;
37203725
3721- ent = string_list_lookup (& symlink_changes , path );
3726+ ent = string_list_lookup (& state -> symlink_changes , path );
37223727 if (!ent ) {
3723- ent = string_list_insert (& symlink_changes , path );
3728+ ent = string_list_insert (& state -> symlink_changes , path );
37243729 ent -> util = (void * )0 ;
37253730 }
37263731 ent -> util = (void * )(what | ((uintptr_t )ent -> util ));
37273732 return (uintptr_t )ent -> util ;
37283733}
37293734
3730- static uintptr_t check_symlink_changes (const char * path )
3735+ static uintptr_t check_symlink_changes (struct apply_state * state , const char * path )
37313736{
37323737 struct string_list_item * ent ;
37333738
3734- ent = string_list_lookup (& symlink_changes , path );
3739+ ent = string_list_lookup (& state -> symlink_changes , path );
37353740 if (!ent )
37363741 return 0 ;
37373742 return (uintptr_t )ent -> util ;
37383743}
37393744
3740- static void prepare_symlink_changes (struct patch * patch )
3745+ static void prepare_symlink_changes (struct apply_state * state , struct patch * patch )
37413746{
37423747 for ( ; patch ; patch = patch -> next ) {
37433748 if ((patch -> old_name && S_ISLNK (patch -> old_mode )) &&
37443749 (patch -> is_rename || patch -> is_delete ))
37453750 /* the symlink at patch->old_name is removed */
3746- register_symlink_changes (patch -> old_name , SYMLINK_GOES_AWAY );
3751+ register_symlink_changes (state , patch -> old_name , SYMLINK_GOES_AWAY );
37473752
37483753 if (patch -> new_name && S_ISLNK (patch -> new_mode ))
37493754 /* the symlink at patch->new_name is created or remains */
3750- register_symlink_changes (patch -> new_name , SYMLINK_IN_RESULT );
3755+ register_symlink_changes (state , patch -> new_name , SYMLINK_IN_RESULT );
37513756 }
37523757}
37533758
@@ -3761,7 +3766,7 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na
37613766 if (!name -> len )
37623767 break ;
37633768 name -> buf [name -> len ] = '\0' ;
3764- change = check_symlink_changes (name -> buf );
3769+ change = check_symlink_changes (state , name -> buf );
37653770 if (change & SYMLINK_IN_RESULT )
37663771 return 1 ;
37673772 if (change & SYMLINK_GOES_AWAY )
@@ -3930,7 +3935,7 @@ static int check_patch_list(struct apply_state *state, struct patch *patch)
39303935{
39313936 int err = 0 ;
39323937
3933- prepare_symlink_changes (patch );
3938+ prepare_symlink_changes (state , patch );
39343939 prepare_fn_table (state , patch );
39353940 while (patch ) {
39363941 if (state -> apply_verbosely )
@@ -4668,6 +4673,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix)
46684673static void clear_apply_state (struct apply_state * state )
46694674{
46704675 string_list_clear (& state -> limit_by_name , 0 );
4676+ string_list_clear (& state -> symlink_changes , 0 );
46714677 strbuf_release (& state -> root );
46724678
46734679 /* &state->fn_table is cleared at the end of apply_patch() */
0 commit comments