1010#include "../config.h"
1111#include "dir.h"
1212#include "win32/fscache.h"
13+ #include "../attr.h"
1314
1415#define HCAST (type , handle ) ((type)(intptr_t)handle)
1516
@@ -2520,7 +2521,38 @@ int link(const char *oldpath, const char *newpath)
25202521 return 0 ;
25212522}
25222523
2523- int symlink (const char * target , const char * link )
2524+ enum symlink_type {
2525+ SYMLINK_TYPE_UNSPECIFIED = 0 ,
2526+ SYMLINK_TYPE_FILE ,
2527+ SYMLINK_TYPE_DIRECTORY ,
2528+ };
2529+
2530+ static enum symlink_type check_symlink_attr (struct index_state * index , const char * link )
2531+ {
2532+ static struct attr_check * check ;
2533+ const char * value ;
2534+
2535+ if (!index )
2536+ return SYMLINK_TYPE_UNSPECIFIED ;
2537+
2538+ if (!check )
2539+ check = attr_check_initl ("symlink" , NULL );
2540+
2541+ git_check_attr (index , link , check );
2542+
2543+ value = check -> items [0 ].value ;
2544+ if (ATTR_UNSET (value ))
2545+ return SYMLINK_TYPE_UNSPECIFIED ;
2546+ if (!strcmp (value , "file" ))
2547+ return SYMLINK_TYPE_FILE ;
2548+ if (!strcmp (value , "dir" ) || !strcmp (value , "directory" ))
2549+ return SYMLINK_TYPE_DIRECTORY ;
2550+
2551+ warning (_ ("ignoring invalid symlink type '%s' for '%s'" ), value , link );
2552+ return SYMLINK_TYPE_UNSPECIFIED ;
2553+ }
2554+
2555+ int mingw_create_symlink (struct index_state * index , const char * target , const char * link )
25242556{
25252557 wchar_t wtarget [MAX_LONG_PATH ], wlink [MAX_LONG_PATH ];
25262558 int len ;
@@ -2540,7 +2572,31 @@ int symlink(const char *target, const char *link)
25402572 if (wtarget [len ] == '/' )
25412573 wtarget [len ] = '\\' ;
25422574
2543- return create_phantom_symlink (wtarget , wlink );
2575+ switch (check_symlink_attr (index , link )) {
2576+ case SYMLINK_TYPE_UNSPECIFIED :
2577+ /* Create a phantom symlink: it is initially created as a file
2578+ * symlink, but may change to a directory symlink later if/when
2579+ * the target exists. */
2580+ return create_phantom_symlink (wtarget , wlink );
2581+ case SYMLINK_TYPE_FILE :
2582+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags ))
2583+ break ;
2584+ return 0 ;
2585+ case SYMLINK_TYPE_DIRECTORY :
2586+ if (!CreateSymbolicLinkW (wlink , wtarget ,
2587+ symlink_directory_flags ))
2588+ break ;
2589+ /* There may be dangling phantom symlinks that point at this
2590+ * one, which should now morph into directory symlinks. */
2591+ process_phantom_symlinks ();
2592+ return 0 ;
2593+ default :
2594+ BUG ("unhandled symlink type" );
2595+ }
2596+
2597+ /* CreateSymbolicLinkW failed. */
2598+ errno = err_win_to_posix (GetLastError ());
2599+ return -1 ;
25442600}
25452601
25462602#ifndef _WINNT_H
0 commit comments