55from .pathutils import Path
66from .tagutils import install_matches_any
77
8+ SCRIPT_CODE = """import sys
9+
10+ # Clear sys.path[0] if it contains this script.
11+ # Be careful to use the most compatible Python code possible.
12+ try:
13+ if sys.path[0]:
14+ if sys.argv[0].startswith(sys.path[0]):
15+ sys.path[0] = ""
16+ else:
17+ open(sys.path[0] + "/" + sys.argv[0], "rb").close()
18+ sys.path[0] = ""
19+ except OSError:
20+ pass
21+ except AttributeError:
22+ pass
23+ except IndexError:
24+ pass
25+
26+ # Replace argv[0] with our executable instead of the script name.
27+ try:
28+ if sys.argv[0][-14:].upper() == ".__SCRIPT__.PY":
29+ sys.argv[0] = sys.argv[0][:-14]
30+ sys.orig_argv[0] = sys.argv[0]
31+ except AttributeError:
32+ pass
33+ except IndexError:
34+ pass
35+
36+ from {mod} import {func}
37+ sys.exit({func}())
38+ """
839
940def _if_exists (launcher , plat ):
1041 suffix = "." + launcher .suffix .lstrip ("." )
@@ -15,13 +46,22 @@ def _if_exists(launcher, plat):
1546
1647
1748def create_alias (cmd , install , alias , target , * , script_code = None , _link = os .link ):
18- p = (cmd .global_dir / alias ["name" ])
49+ p = cmd .global_dir / alias ["name" ]
50+ if not p .match ("*.exe" ):
51+ p = p .with_name (p .name + ".exe" )
1952 target = Path (target )
2053 ensure_tree (p )
2154 launcher = cmd .launcher_exe
2255 if alias .get ("windowed" ):
2356 launcher = cmd .launcherw_exe or launcher
2457
58+ alias_written = cmd .scratch .setdefault ("aliasutils.create_alias.alias_written" , set ())
59+ n = p .stem .casefold ()
60+ if n in alias_written :
61+ # We've already written this alias in this session, so skip it.
62+ return
63+ alias_written .add (n )
64+
2565 plat = install ["tag" ].rpartition ("-" )[- 1 ]
2666 if plat :
2767 LOGGER .debug ("Checking for launcher for platform -%s" , plat )
@@ -60,7 +100,6 @@ def create_alias(cmd, install, alias, target, *, script_code=None, _link=os.link
60100 LOGGER .debug ("Failed to read existing alias launcher." )
61101
62102 launcher_remap = cmd .scratch .setdefault ("aliasutils.create_alias.launcher_remap" , {})
63-
64103 if existing_bytes == launcher_bytes :
65104 # Valid existing launcher, so save its path in case we need it later
66105 # for a hard link.
@@ -106,7 +145,7 @@ def create_alias(cmd, install, alias, target, *, script_code=None, _link=os.link
106145 if do_update :
107146 p_target .write_text (str (target ), encoding = "utf-8" )
108147
109- p_script = p .with_name (p .name + "-script .py" )
148+ p_script = p .with_name (p .name + ".__script__ .py" )
110149 if script_code :
111150 do_update = True
112151 try :
@@ -126,6 +165,24 @@ def create_alias(cmd, install, alias, target, *, script_code=None, _link=os.link
126165 LOGGER .info ("Failed to remove %s." , p_script , exc_info = True )
127166
128167
168+ def cleanup_alias (cmd ):
169+ if not cmd .global_dir or not cmd .global_dir .is_dir ():
170+ return
171+
172+ alias_written = cmd .scratch .get ("aliasutils.create_alias.alias_written" ) or ()
173+
174+ for alias in cmd .global_dir .glob ("*.exe" ):
175+ target = alias .with_name (alias .name + ".__target__" )
176+ script = alias .with_name (alias .name + ".__script__.py" )
177+ if alias .stem .casefold () not in alias_written :
178+ LOGGER .debug ("Unlink %s" , alias )
179+ unlink (alias , f"Attempting to remove { alias } is taking some time. " +
180+ "Ensure it is not is use, and please continue to wait " +
181+ "or press Ctrl+C to abort." )
182+ unlink (target )
183+ unlink (script )
184+
185+
129186def _parse_entrypoint_line (line ):
130187 line = line .partition ("#" )[0 ]
131188 name , sep , rest = line .partition ("=" )
@@ -170,7 +227,7 @@ def _scan_one(root):
170227 if name and mod and func :
171228 yield (
172229 {** alias , "name" : name },
173- f"import sys; from { mod } import { func } ; sys.exit( { func } ())" ,
230+ SCRIPT_CODE . format ( mod = mod , func = func ) ,
174231 )
175232
176233
0 commit comments