33from .exceptions import FilesInUseError , NoLauncherTemplateError
44from .fsutils import atomic_unlink , ensure_tree , unlink
55from .logging import LOGGER
6- from .pathutils import Path
6+ from .pathutils import Path , relative_to
77from .tagutils import install_matches_any
88
99_EXE = ".exe" .casefold ()
@@ -105,16 +105,18 @@ def _create_alias(
105105 if windowed :
106106 launcher = cmd .launcherw_exe or launcher
107107
108+ chosen_by = "default"
108109 if plat :
109- LOGGER .debug ("Checking for launcher for platform -%s" , plat )
110110 launcher = _if_exists (launcher , f"-{ plat } " )
111+ chosen_by = "platform tag"
111112 if not launcher .is_file ():
112- LOGGER .debug ("Checking for launcher for default platform %s" , cmd .default_platform )
113113 launcher = _if_exists (launcher , cmd .default_platform )
114+ chosen_by = "default platform"
114115 if not launcher .is_file ():
115- LOGGER .debug ("Checking for launcher for -64" )
116116 launcher = _if_exists (launcher , "-64" )
117- LOGGER .debug ("Create %s linking to %s using %s" , name , target , launcher )
117+ chosen_by = "fallback default"
118+ LOGGER .debug ("Create %s for %s using %s, chosen by %s" , name ,
119+ relative_to (target , cmd .install_dir ), launcher , chosen_by )
118120 if not launcher or not launcher .is_file ():
119121 raise NoLauncherTemplateError ()
120122
@@ -128,8 +130,9 @@ def _create_alias(
128130 LOGGER .debug ("Failed to read %s" , launcher , exc_info = True )
129131 return
130132
133+ force = getattr (cmd , "force" , False )
131134 existing_bytes = b''
132- if getattr ( cmd , " force" , False ) :
135+ if force :
133136 # Only expect InstallCommand to have .force
134137 unlink (p )
135138 else :
@@ -146,8 +149,10 @@ def _create_alias(
146149 if existing_bytes != launcher_bytes and allow_link and _link :
147150 # Try to find an existing launcher we can hard-link
148151 launcher2 = launcher_remap .get (launcher .name )
149- if not launcher2 :
150- # None known, so search existing files
152+ if (not launcher2 or not launcher2 .is_file ()) and not force :
153+ # None known, so search existing files. Or, user is forcing us, so
154+ # we only want to use an existing launcher if we've cached it this
155+ # session.
151156 try :
152157 LOGGER .debug ("Searching %s for suitable launcher to link" , cmd .global_dir )
153158 for p2 in cmd .global_dir .glob ("*.exe" ):
@@ -165,10 +170,11 @@ def _create_alias(
165170 except Exception :
166171 LOGGER .debug ("Failed to find existing launcher" , exc_info = True )
167172
168- if launcher2 :
173+ if launcher2 and launcher2 . is_file () :
169174 # We know that the target either doesn't exist or needs replacing
170175 unlink (p )
171176 try :
177+ LOGGER .debug ("Creating %s as hard link to %s" , p , launcher2 )
172178 _link (launcher2 , p )
173179 existing_bytes = launcher_bytes
174180 launcher_remap [launcher .name ] = launcher2
@@ -256,13 +262,13 @@ def _readlines(path):
256262 return
257263
258264
259- def _scan_one (install , root ):
265+ def _scan_one (cmd , install , root ):
260266 # Scan d for dist-info directories with entry_points.txt
261267 dist_info = [d for d in root .glob ("*.dist-info" ) if d .is_dir ()]
262268 entrypoints = [f for f in [d / "entry_points.txt" for d in dist_info ] if f .is_file ()]
263269 if len (entrypoints ):
264270 LOGGER .debug ("Found %i entry_points.txt files in %i dist-info in %s" ,
265- len (entrypoints ), len (dist_info ), root )
271+ len (entrypoints ), len (dist_info ), relative_to ( root , cmd . install_dir ) )
266272
267273 # Filter down to [console_scripts] and [gui_scripts]
268274 for ep in entrypoints :
@@ -281,10 +287,10 @@ def _scan_one(install, root):
281287 mod = mod , func = func , ** alias )
282288
283289
284- def _scan (install , prefix , dirs ):
290+ def _scan (cmd , install , prefix , dirs ):
285291 for dirname in dirs or ():
286292 root = prefix / dirname
287- yield from _scan_one (install , root )
293+ yield from _scan_one (cmd , install , root )
288294
289295
290296def calculate_aliases (cmd , install , * , _scan = _scan ):
@@ -326,7 +332,7 @@ def calculate_aliases(cmd, install, *, _scan=_scan):
326332 site_dirs = s .get ("dirs" , ())
327333 break
328334
329- for ai in _scan (install , prefix , site_dirs ):
335+ for ai in _scan (cmd , install , prefix , site_dirs ):
330336 if ai .windowed and default_alias_w :
331337 yield ai .replace (target = default_alias_w .target )
332338 elif not ai .windowed and default_alias :
0 commit comments