@@ -85,7 +85,16 @@ def _if_exists(launcher, plat):
8585 return launcher
8686
8787
88- def _create_alias (cmd , * , name , target , plat = None , windowed = 0 , script_code = None , _link = os .link ):
88+ def _create_alias (
89+ cmd ,
90+ * ,
91+ name ,
92+ target ,
93+ plat = None ,
94+ windowed = 0 ,
95+ script_code = None ,
96+ allow_link = True ,
97+ _link = os .link ):
8998 p = cmd .global_dir / name
9099 if not p .match ("*.exe" ):
91100 p = p .with_name (p .name + ".exe" )
@@ -129,12 +138,27 @@ def _create_alias(cmd, *, name, target, plat=None, windowed=0, script_code=None,
129138 LOGGER .debug ("Failed to read existing alias launcher." )
130139
131140 launcher_remap = cmd .scratch .setdefault ("aliasutils.create_alias.launcher_remap" , {})
132- if existing_bytes == launcher_bytes :
141+ if not allow_link or not _link :
142+ # If links are disallowed, always replace the target with a copy.
143+ unlink (p )
144+ try :
145+ p .write_bytes (launcher_bytes )
146+ LOGGER .debug ("Created %s as copy of %s" , p .name , launcher .name )
147+ launcher_remap [launcher .name ] = p
148+ except OSError :
149+ LOGGER .error ("Failed to create global command %s." , name )
150+ LOGGER .debug ("TRACEBACK" , exc_info = True )
151+ elif existing_bytes == launcher_bytes :
133152 # Valid existing launcher, so save its path in case we need it later
134153 # for a hard link.
135154 launcher_remap .setdefault (launcher .name , p )
136155 else :
137- # First try and create a hard link
156+ # Links are allowed and we need to create one, so try to make a link,
157+ # falling back to a link to another existing alias (that we've checked
158+ # already during this run), and then falling back to a copy.
159+ # This handles the case where our links are on a different volume to the
160+ # install (so hard links don't work), but limits us to only a single
161+ # copy (each) of the redirector(s), thus saving space.
138162 unlink (p )
139163 try :
140164 _link (launcher , p )
@@ -305,7 +329,7 @@ def calculate_aliases(cmd, install, *, _scan=_scan):
305329 yield ai .replace (target = default_alias .target )
306330
307331
308- def create_aliases (cmd , aliases , * , _create_alias = _create_alias ):
332+ def create_aliases (cmd , aliases , * , allow_link = True , _create_alias = _create_alias ):
309333 if not cmd .global_dir :
310334 return
311335
@@ -337,6 +361,7 @@ def create_aliases(cmd, aliases, *, _create_alias=_create_alias):
337361 target = target ,
338362 script_code = alias .script_code ,
339363 windowed = alias .windowed ,
364+ allow_link = allow_link ,
340365 )
341366 except NoLauncherTemplateError :
342367 if install_matches_any (alias .install , getattr (cmd , "tags" , None )):
0 commit comments