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
@@ -2529,7 +2530,38 @@ int link(const char *oldpath, const char *newpath)
25292530 return 0 ;
25302531}
25312532
2532- int symlink (const char * target , const char * link )
2533+ enum symlink_type {
2534+ SYMLINK_TYPE_UNSPECIFIED = 0 ,
2535+ SYMLINK_TYPE_FILE ,
2536+ SYMLINK_TYPE_DIRECTORY ,
2537+ };
2538+
2539+ static enum symlink_type check_symlink_attr (struct index_state * index , const char * link )
2540+ {
2541+ static struct attr_check * check ;
2542+ const char * value ;
2543+
2544+ if (!index )
2545+ return SYMLINK_TYPE_UNSPECIFIED ;
2546+
2547+ if (!check )
2548+ check = attr_check_initl ("symlink" , NULL );
2549+
2550+ git_check_attr (index , link , check );
2551+
2552+ value = check -> items [0 ].value ;
2553+ if (ATTR_UNSET (value ))
2554+ return SYMLINK_TYPE_UNSPECIFIED ;
2555+ if (!strcmp (value , "file" ))
2556+ return SYMLINK_TYPE_FILE ;
2557+ if (!strcmp (value , "dir" ) || !strcmp (value , "directory" ))
2558+ return SYMLINK_TYPE_DIRECTORY ;
2559+
2560+ warning (_ ("ignoring invalid symlink type '%s' for '%s'" ), value , link );
2561+ return SYMLINK_TYPE_UNSPECIFIED ;
2562+ }
2563+
2564+ int mingw_create_symlink (struct index_state * index , const char * target , const char * link )
25332565{
25342566 wchar_t wtarget [MAX_LONG_PATH ], wlink [MAX_LONG_PATH ];
25352567 int len ;
@@ -2549,7 +2581,31 @@ int symlink(const char *target, const char *link)
25492581 if (wtarget [len ] == '/' )
25502582 wtarget [len ] = '\\' ;
25512583
2552- return create_phantom_symlink (wtarget , wlink );
2584+ switch (check_symlink_attr (index , link )) {
2585+ case SYMLINK_TYPE_UNSPECIFIED :
2586+ /* Create a phantom symlink: it is initially created as a file
2587+ * symlink, but may change to a directory symlink later if/when
2588+ * the target exists. */
2589+ return create_phantom_symlink (wtarget , wlink );
2590+ case SYMLINK_TYPE_FILE :
2591+ if (!CreateSymbolicLinkW (wlink , wtarget , symlink_file_flags ))
2592+ break ;
2593+ return 0 ;
2594+ case SYMLINK_TYPE_DIRECTORY :
2595+ if (!CreateSymbolicLinkW (wlink , wtarget ,
2596+ symlink_directory_flags ))
2597+ break ;
2598+ /* There may be dangling phantom symlinks that point at this
2599+ * one, which should now morph into directory symlinks. */
2600+ process_phantom_symlinks ();
2601+ return 0 ;
2602+ default :
2603+ BUG ("unhandled symlink type" );
2604+ }
2605+
2606+ /* CreateSymbolicLinkW failed. */
2607+ errno = err_win_to_posix (GetLastError ());
2608+ return -1 ;
25532609}
25542610
25552611#ifndef _WINNT_H
0 commit comments