1+ #! /usr/bin/env -S pkgx bash
2+ # shellcheck shell=bash
3+
4+ # python virtual-envs are not relocatable
5+ # our only working choice is to rewrite these files and symlinks every time
6+ # because we promise that pkgx is relocatable *at any time*
7+ # FIXME requiring sed is a bit lame
8+
9+ if test -z " $VIRTUAL_ENV " ; then
10+ echo " error: VIRTUAL_ENV not set" >&2
11+ exit 1
12+ fi
13+
14+ mkdir -p " $VIRTUAL_ENV /../bin"
15+
16+ CMD_NAME=" $1 "
17+
18+ cat << EOF > "$VIRTUAL_ENV "/../bin/"$CMD_NAME "
19+ #!/usr/bin/env python
20+
21+ import os
22+ import sys
23+ import glob
24+ import shutil
25+ from pathlib import Path
26+
27+ # Determine directories and paths
28+ script_dir = os.path.dirname(os.path.realpath(__file__))
29+ virtual_env = os.path.normpath(os.path.join(script_dir, '..', 'venv'))
30+ arg0 = os.path.basename(sys.argv[0])
31+ python_path = shutil.which('python')
32+ python_home = os.path.dirname(python_path)
33+
34+ # Write pyvenv.cfg file
35+ pyvenv_cfg_path = os.path.join(virtual_env, 'pyvenv.cfg')
36+ with open(pyvenv_cfg_path, 'w') as f:
37+ f.write(f"home = {python_home}\ninclude-system-site-packages = false\nexecutable = {python_path}\n")
38+
39+ new_first_line = b"#!" + os.path.join(virtual_env, 'bin', 'python').encode('utf-8') + b"\n"
40+
41+ # Go through files in the bin directory
42+ for filepath in glob.glob(os.path.join(virtual_env, 'bin', '*')):
43+ if os.path.isfile(filepath) and not os.path.islink(filepath):
44+ with open(filepath, 'rb+') as f:
45+ first_two_chars = f.read(2)
46+
47+ if first_two_chars == b'#!':
48+ old_first_line = first_two_chars + f.readline() # Read the rest of the first line
49+
50+ if old_first_line.strip().endswith(b"python") and old_first_line != new_first_line:
51+ rest_of_file = f.read()
52+ f.seek(0)
53+ f.write(new_first_line + rest_of_file)
54+ f.truncate()
55+
56+ # Create symlink to the specified Python version in the virtual environment
57+ python_symlink = os.path.join(virtual_env, 'bin', 'python')
58+
59+ # Remove the symbolic link if it already exists
60+ if os.path.islink(python_symlink) or os.path.exists(python_symlink):
61+ os.remove(python_symlink)
62+
63+ os.symlink(python_path, python_symlink)
64+
65+ # Execute the corresponding script in the virtual environment
66+ arg0 = os.path.join(virtual_env, 'bin', arg0)
67+ args = sys.argv[1:]
68+ args.insert(0, arg0)
69+ os.execv(arg0, args)
70+ EOF
71+
72+ chmod +x " $VIRTUAL_ENV /../bin/$CMD_NAME "
0 commit comments