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
@@ -2410,7 +2411,38 @@ int link(const char *oldpath, const char *newpath)
24102411 return 0 ;
24112412}
24122413
2413- int symlink (const char * target , const char * link )
2414+ enum symlink_type {
2415+ SYMLINK_TYPE_UNSPECIFIED = 0 ,
2416+ SYMLINK_TYPE_FILE ,
2417+ SYMLINK_TYPE_DIRECTORY ,
2418+ };
2419+
2420+ static enum symlink_type check_symlink_attr (struct index_state * index , const char * link )
2421+ {
2422+ static struct attr_check * check ;
2423+ const char * value ;
2424+
2425+ if (!index )
2426+ return SYMLINK_TYPE_UNSPECIFIED ;
2427+
2428+ if (!check )
2429+ check = attr_check_initl ("symlink" , NULL );
2430+
2431+ git_check_attr (index , link , check );
2432+
2433+ value = check -> items [0 ].value ;
2434+ if (ATTR_UNSET (value ))
2435+ return SYMLINK_TYPE_UNSPECIFIED ;
2436+ if (!strcmp (value , "file" ))
2437+ return SYMLINK_TYPE_FILE ;
2438+ if (!strcmp (value , "dir" ) || !strcmp (value , "directory" ))
2439+ return SYMLINK_TYPE_DIRECTORY ;
2440+
2441+ warning (_ ("ignoring invalid symlink type '%s' for '%s'" ), value , link );
2442+ return SYMLINK_TYPE_UNSPECIFIED ;
2443+ }
2444+
2445+ int mingw_create_symlink (struct index_state * index , const char * target , const char * link )
24142446{
24152447 wchar_t wtarget [MAX_LONG_PATH ], wlink [MAX_LONG_PATH ];
24162448 int len ;
@@ -2430,7 +2462,31 @@ int symlink(const char *target, const char *link)
24302462 if (wtarget [len ] == '/' )
24312463 wtarget [len ] = '\\' ;
24322464
2433- return create_phantom_symlink (wtarget , wlink );
2465+ switch (check_symlink_attr (index , link )) {
2466+ case SYMLINK_TYPE_UNSPECIFIED :
2467+ /* Create a phantom symlink: it is initially created as a file
2468+ * symlink, but may change to a directory symlink later if/when
2469+ * the target exists. */
2470+ return create_phantom_symlink (wtarget , wlink );
2471+ case SYMLINK_TYPE_FILE :
2472+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags ))
2473+ break ;
2474+ return 0 ;
2475+ case SYMLINK_TYPE_DIRECTORY :
2476+ if (!CreateSymbolicLinkW (wlink , wtarget ,
2477+ symlink_directory_flags ))
2478+ break ;
2479+ /* There may be dangling phantom symlinks that point at this
2480+ * one, which should now morph into directory symlinks. */
2481+ process_phantom_symlinks ();
2482+ return 0 ;
2483+ default :
2484+ BUG ("unhandled symlink type" );
2485+ }
2486+
2487+ /* CreateSymbolicLinkW failed. */
2488+ errno = err_win_to_posix (GetLastError ());
2489+ return -1 ;
24342490}
24352491
24362492#ifndef _WINNT_H
0 commit comments