99#include "win32/lazyload.h"
1010#include "../config.h"
1111#include "dir.h"
12+ #include "../attr.h"
1213
1314#define HCAST (type , handle ) ((type)(intptr_t)handle)
1415
@@ -2404,7 +2405,38 @@ int link(const char *oldpath, const char *newpath)
24042405 return 0 ;
24052406}
24062407
2407- int symlink (const char * target , const char * link )
2408+ enum symlink_type {
2409+ SYMLINK_TYPE_UNSPECIFIED = 0 ,
2410+ SYMLINK_TYPE_FILE ,
2411+ SYMLINK_TYPE_DIRECTORY ,
2412+ };
2413+
2414+ static enum symlink_type check_symlink_attr (struct index_state * index , const char * link )
2415+ {
2416+ static struct attr_check * check ;
2417+ const char * value ;
2418+
2419+ if (!index )
2420+ return SYMLINK_TYPE_UNSPECIFIED ;
2421+
2422+ if (!check )
2423+ check = attr_check_initl ("symlink" , NULL );
2424+
2425+ git_check_attr (index , link , check );
2426+
2427+ value = check -> items [0 ].value ;
2428+ if (ATTR_UNSET (value ))
2429+ return SYMLINK_TYPE_UNSPECIFIED ;
2430+ if (!strcmp (value , "file" ))
2431+ return SYMLINK_TYPE_FILE ;
2432+ if (!strcmp (value , "dir" ) || !strcmp (value , "directory" ))
2433+ return SYMLINK_TYPE_DIRECTORY ;
2434+
2435+ warning (_ ("ignoring invalid symlink type '%s' for '%s'" ), value , link );
2436+ return SYMLINK_TYPE_UNSPECIFIED ;
2437+ }
2438+
2439+ int mingw_create_symlink (struct index_state * index , const char * target , const char * link )
24082440{
24092441 wchar_t wtarget [MAX_LONG_PATH ], wlink [MAX_LONG_PATH ];
24102442 int len ;
@@ -2424,7 +2456,31 @@ int symlink(const char *target, const char *link)
24242456 if (wtarget [len ] == '/' )
24252457 wtarget [len ] = '\\' ;
24262458
2427- return create_phantom_symlink (wtarget , wlink );
2459+ switch (check_symlink_attr (index , link )) {
2460+ case SYMLINK_TYPE_UNSPECIFIED :
2461+ /* Create a phantom symlink: it is initially created as a file
2462+ * symlink, but may change to a directory symlink later if/when
2463+ * the target exists. */
2464+ return create_phantom_symlink (wtarget , wlink );
2465+ case SYMLINK_TYPE_FILE :
2466+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags ))
2467+ break ;
2468+ return 0 ;
2469+ case SYMLINK_TYPE_DIRECTORY :
2470+ if (!CreateSymbolicLinkW (wlink , wtarget ,
2471+ symlink_directory_flags ))
2472+ break ;
2473+ /* There may be dangling phantom symlinks that point at this
2474+ * one, which should now morph into directory symlinks. */
2475+ process_phantom_symlinks ();
2476+ return 0 ;
2477+ default :
2478+ BUG ("unhandled symlink type" );
2479+ }
2480+
2481+ /* CreateSymbolicLinkW failed. */
2482+ errno = err_win_to_posix (GetLastError ());
2483+ return -1 ;
24282484}
24292485
24302486#ifndef _WINNT_H
0 commit comments