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
@@ -2509,7 +2510,38 @@ int link(const char *oldpath, const char *newpath)
25092510 return 0 ;
25102511}
25112512
2512- int symlink (const char * target , const char * link )
2513+ enum symlink_type {
2514+ SYMLINK_TYPE_UNSPECIFIED = 0 ,
2515+ SYMLINK_TYPE_FILE ,
2516+ SYMLINK_TYPE_DIRECTORY ,
2517+ };
2518+
2519+ static enum symlink_type check_symlink_attr (struct index_state * index , const char * link )
2520+ {
2521+ static struct attr_check * check ;
2522+ const char * value ;
2523+
2524+ if (!index )
2525+ return SYMLINK_TYPE_UNSPECIFIED ;
2526+
2527+ if (!check )
2528+ check = attr_check_initl ("symlink" , NULL );
2529+
2530+ git_check_attr (index , link , check );
2531+
2532+ value = check -> items [0 ].value ;
2533+ if (ATTR_UNSET (value ))
2534+ return SYMLINK_TYPE_UNSPECIFIED ;
2535+ if (!strcmp (value , "file" ))
2536+ return SYMLINK_TYPE_FILE ;
2537+ if (!strcmp (value , "dir" ) || !strcmp (value , "directory" ))
2538+ return SYMLINK_TYPE_DIRECTORY ;
2539+
2540+ warning (_ ("ignoring invalid symlink type '%s' for '%s'" ), value , link );
2541+ return SYMLINK_TYPE_UNSPECIFIED ;
2542+ }
2543+
2544+ int mingw_create_symlink (struct index_state * index , const char * target , const char * link )
25132545{
25142546 wchar_t wtarget [MAX_LONG_PATH ], wlink [MAX_LONG_PATH ];
25152547 int len ;
@@ -2529,7 +2561,31 @@ int symlink(const char *target, const char *link)
25292561 if (wtarget [len ] == '/' )
25302562 wtarget [len ] = '\\' ;
25312563
2532- return create_phantom_symlink (wtarget , wlink );
2564+ switch (check_symlink_attr (index , link )) {
2565+ case SYMLINK_TYPE_UNSPECIFIED :
2566+ /* Create a phantom symlink: it is initially created as a file
2567+ * symlink, but may change to a directory symlink later if/when
2568+ * the target exists. */
2569+ return create_phantom_symlink (wtarget , wlink );
2570+ case SYMLINK_TYPE_FILE :
2571+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags ))
2572+ break ;
2573+ return 0 ;
2574+ case SYMLINK_TYPE_DIRECTORY :
2575+ if (!CreateSymbolicLinkW (wlink , wtarget ,
2576+ symlink_directory_flags ))
2577+ break ;
2578+ /* There may be dangling phantom symlinks that point at this
2579+ * one, which should now morph into directory symlinks. */
2580+ process_phantom_symlinks ();
2581+ return 0 ;
2582+ default :
2583+ BUG ("unhandled symlink type" );
2584+ }
2585+
2586+ /* CreateSymbolicLinkW failed. */
2587+ errno = err_win_to_posix (GetLastError ());
2588+ return -1 ;
25332589}
25342590
25352591#ifndef _WINNT_H
0 commit comments