53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
import argparse
|
|
import hashlib
|
|
from pathlib import Path
|
|
import platform
|
|
import subprocess
|
|
import tempfile
|
|
import urllib.request
|
|
|
|
VERSION = '4.7.4.260706075'
|
|
SHA256 = {
|
|
'x86_64': '9233ed1b87d3e6b45722278f3c286dcd41e83da778bd0f80a1dd04949696ad93',
|
|
'aarch64': '162ae55b317660f196b2e73d566bdb45c1e990ed4cc140709d25d97b9ef366b0',
|
|
}
|
|
|
|
def install(destination: Path) -> Path:
|
|
architecture = platform.machine()
|
|
if architecture not in SHA256:
|
|
raise RuntimeError('the pinned engraver requires an x86_64 or aarch64 Linux build host')
|
|
destination = destination.resolve()
|
|
executable = destination / 'squashfs-root' / 'AppRun'
|
|
marker = destination / 'sha256'
|
|
if executable.is_file() and marker.is_file() and marker.read_text().strip() == SHA256[architecture]:
|
|
return executable
|
|
if destination.exists() and any(destination.iterdir()):
|
|
raise RuntimeError(f'{destination} contains a different or incomplete installation; choose an empty directory')
|
|
destination.mkdir(parents=True, exist_ok=True)
|
|
name = f'MuseScore-Studio-{VERSION}-{architecture}.AppImage'
|
|
url = f'https://github.com/musescore/MuseScore/releases/download/v4.7.4/{name}'
|
|
with tempfile.TemporaryDirectory(prefix='vamp-musescore-download-') as temporary:
|
|
archive = Path(temporary) / name
|
|
digest = hashlib.sha256()
|
|
with urllib.request.urlopen(url, timeout=120) as response, archive.open('wb') as output:
|
|
while chunk := response.read(1024 * 1024):
|
|
digest.update(chunk)
|
|
output.write(chunk)
|
|
if digest.hexdigest() != SHA256[architecture]:
|
|
raise RuntimeError('MuseScore AppImage checksum mismatch')
|
|
archive.chmod(0o755)
|
|
subprocess.run([str(archive), '--appimage-extract'], cwd=destination, check=True, stdout=subprocess.DEVNULL)
|
|
if not executable.is_file():
|
|
raise RuntimeError('MuseScore AppImage does not contain AppRun')
|
|
marker.write_text(SHA256[architecture] + '\n')
|
|
return executable
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description='Install the pinned build-only MuseScore engraver without FUSE.')
|
|
parser.add_argument('destination', type=Path)
|
|
print(install(parser.parse_args().destination))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|