Last active
January 22, 2023 16:30
-
-
Save joshcangit/2e2f4ad62ba3122c4ab2e6adedbb1b44 to your computer and use it in GitHub Desktop.
Wrapper script for meson.pyz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from asyncio import run as arun | |
from functools import partial as fpartial | |
from importlib import util as libutil | |
from pathlib import Path | |
from re import sub | |
from shutil import move, which | |
from subprocess import run, PIPE, STDOUT | |
from sys import argv, executable, stdout | |
from tarfile import open as topen | |
from tempfile import TemporaryDirectory | |
from zipapp import create_archive | |
try: from packaging.version import Version | |
except ModuleNotFoundError: | |
from pkg_resources import packaging | |
Version = packaging.version.Version | |
del packaging | |
cmds = ["aria2c","xh","curl","wget"] | |
cmds[:] = [x for x in cmds if which(x)] | |
libr = "requests" | |
if(libutil.find_spec(libr)): | |
from requests import get as getr, head as headr | |
cmds += [libr] | |
def if_exists(fp): | |
if(Path(fp).exists()): | |
return fp | |
else: return None | |
def cmd_output(cmd): | |
result = run(cmd, shell=True, text=True, check=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT) | |
return result.stdout | |
def tag_version(url): | |
return sub(r'.+\/(.+)', '\\1', url) | |
def file_url(url): | |
return sub(r'(.+)releases\/tag(.+)', '\\1archive/refs/tags\\2.tar.gz', url) | |
async def location(cmds, url): | |
cmds = [x for x in cmds if x != "aria2c"] | |
xh_v = cmd_output('xh --version').split() if "xh" in cmds else ["xh","1"] | |
cmd_dict = { | |
"xh": f"xh HEAD {url} User-Agent:'{xh_v[0]}:{xh_v[1]}' --no-check-status -h", | |
"curl": f"curl -ISs {url}", | |
"wget": f"wget --recursive=off --method=HEAD --max-redirect=1 {url}", | |
libr: None | |
} | |
cmd = cmd_dict[cmds[0]] | |
if (cmd): | |
return [x for x in cmd_output(cmd).splitlines() if x.startswith("location") or x.startswith("Location")][0].split()[1] | |
else: | |
response = headr(url) | |
return response.headers["Location"] | |
async def write_loop(r,f,length=None): | |
part = 0 | |
for chunk in r.iter_content(chunk_size=1024): | |
f.write(chunk) | |
if (length): | |
part += len(chunk) | |
percent = int(part / length * 100) if (length) else 0 | |
stdout.write(f"\rProgress: {percent}%") | |
stdout.flush() | |
stdout.write('\rDownload completed.\n') | |
async def file_writer(r,file,file_size=None): | |
with open(file, 'wb') as f: | |
await write_loop(r,f,int(file_size)) if (file_size) else await write_loop(r,f) | |
async def get_request(url,file,headers=None): | |
with getr(url, headers=headers, stream=True) as r: | |
print(f"Downloading to {file}") | |
if (headers): r.raw.read = fpartial(r.raw.read, decode_content=True) | |
file_size = r.headers.get('content-length') | |
await file_writer(r,file,file_size) if (file_size) else await file_writer(r,file) | |
async def download_file(url, file=None, encoding=None): | |
if (file is None): file = url.split('/')[-1] | |
headers = {'Accept-Encoding': encoding} if (encoding) else None | |
await get_request(url,file,headers) | |
async def install(cmds, url, ver, exe): | |
file = "meson.tgz" | |
options = { | |
"source": f"meson-{ver}", | |
"outfile": exe, | |
"interpreter": "/usr/bin/env python3", | |
"compress": True | |
} | |
encoding = "zstd, gzip, deflate" | |
with TemporaryDirectory() as d: | |
cmd_dict = { | |
"aria2c": f"aria2c {url} -d '{d}' -o '{file}' -j5 -x10 -s8 -k1M --optimize-concurrent-downloads --header='Accept-Encoding: {encoding}'", | |
"xh": f"xh {url} Accept-Encoding:'{encoding}' -Fdo '{Path(d) / file}'", | |
"curl": f"curl -L {url} -o '{Path(d) / file}' --compressed -H 'Accept-Encoding: {encoding}'", | |
"wget": f"wget {url} -P '{d}' -O '{file}' --header='Accept-Encoding: {encoding}'", | |
libr: None | |
} | |
cmd = cmd_dict[cmds[0]] | |
file = Path(d) / file | |
run(cmd, shell=True, check=True) if (cmd) else await download_file(url,file,encoding) | |
with topen(file) as tar: | |
maindir = options["source"] | |
group = [ | |
tarinfo for tarinfo in tar.getmembers() | |
if tarinfo.name.startswith(f"{maindir}/mesonbuild/") or tarinfo.name == f"{maindir}/meson.py" | |
] | |
tar.extractall(d,members=group) | |
Path(file).unlink() | |
source = Path(d, options["source"]).resolve() | |
move(source / 'meson.py', Path(d, '__main__.py')) | |
move(source / 'mesonbuild', Path(d, 'mesonbuild')) | |
Path(source).rmdir() | |
create_archive(d, interpreter=options["interpreter"], target=options["outfile"], compressed=options["compress"]) | |
if (if_exists(exe)): | |
try: move(exe,dirpath / exe) | |
except IOError: | |
admin_cmd = f"from pathlib import Path\nfrom shutil import copymode, move, chown\nmove('{exe}','{dirpath / exe}')\nchown('{dirpath / exe}',user='{Path(dirpath).owner()}',group='{Path(dirpath).group()}')\ncopymode('{__file__}','{dirpath / exe}')" | |
run(f'sudo python -c "{admin_cmd}"', shell=True, check=True) | |
meson = "meson.pyz" | |
release = "https://github.com/mesonbuild/meson/releases/latest" | |
dirpath = Path(__file__).parent.absolute() | |
subcmd = "pyz" | |
if (if_exists(dirpath / meson)): | |
if (argv == [argv[0], subcmd]): | |
tag_url = arun(location(cmds, release)) | |
latest_version = tag_version(tag_url) | |
current_version = cmd_output(f"{executable} {dirpath / meson} --version").strip() | |
if (Version(current_version) < Version(latest_version)): | |
arun(install(cmds, file_url(tag_url), latest_version, meson)) | |
else: print("Meson is up to date") | |
else: | |
argv[:] = [f"\"{x}\"" if " " in x else x for x in argv] | |
run([executable, f"{dirpath / meson}"] + argv[1:]) | |
else: | |
if (argv == [argv[0], subcmd]): | |
tag_url = arun(location(cmds, release)) | |
latest_version = tag_version(tag_url) | |
arun(install(cmds, file_url(tag_url), latest_version, meson)) | |
else: print(f"\nCommand 'meson' not found, but can be installed with:\n\nmeson {subcmd}\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wrapper script for
meson.pyz
Registering as command
On Linux / BSD / macOS
PATH environment
Then, add the contents as below to a profile file, corresponding to on the folder you made, to append to your PATH environment.
e.g.
~/.meson/bin
Rename file
On Windows
Path environment
Place this script inside any folder in your Path environment.
Then, open
sysdm.cpl
a.k.a System Properties.New
orBrowse...
button.Add .cmd script.
Create a
meson.cmd
script, in the same folder, with the contents as belowDo not use this with another Meson instance installed.
This is if you prefer to use Meson directly from the GitHub releases through this script.
Dependencies
Python3
This script requires Python 3.6 and above because I have use formatted string literals.
Anyway, Meson itself requires at least Python 3.7.
Download functionality
For this script to be able to download, any one of 4 tools below is required.
xh
curl
wget
There are a few ways to install this.
This can be installed using
pip install requests
.This can also be installed as Linux packages named
python3-requests
or as with Archpython-requests
.sudo
On Windows, you can install
gsudo
if just in case when this script usessudo
for admin rights to a folder.Optional dependencies
aria2
There's another tool called aria2 but it cannot send output for this script to fetch the download URL.
It can only be used for downloading, albeit very fast with it's multi-connection download capability.
Any of the other tools is still needed.