0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-14 14:10:33 +03:00
nixpkgs/pkgs/development/compilers/flutter/update/update.py
sternenseemann 6dc3672c15 flutter/update: add .in extensions to Nix expression template files
Use autotools inspired extensions (as syntax sort of matches) to make
clear that these are not Nix expressions yet and don't necessarily parse
or evaluate.
2024-01-31 20:30:34 +01:00

339 lines
9.9 KiB
Python
Executable file

#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.pyyaml
import shutil
import json
import urllib.request
import tempfile
from sys import exit
import os
import subprocess
import re
import json
import argparse
import yaml
import json
NIXPKGS_ROOT = subprocess.Popen(['git',
'rev-parse',
'--show-toplevel'],
stdout=subprocess.PIPE,
text=True).communicate()[0].strip()
def load_code(name, **kwargs):
with open(f"{NIXPKGS_ROOT}/pkgs/development/compilers/flutter/update/{name}.in", 'r') as f:
code = f.read()
for (key, value) in kwargs.items():
code = code.replace(f"@{key}@", value)
return code
# Return out paths
def nix_build(code):
temp = tempfile.NamedTemporaryFile(mode='w')
temp.write(code)
temp.flush()
os.fsync(temp.fileno())
process = subprocess.Popen(
[
"nix-build",
"--impure",
"--no-out-link",
"--expr",
f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"],
stdout=subprocess.PIPE,
text=True)
process.wait()
temp.close()
return process.stdout.read().strip().splitlines()[0]
# Return errors
def nix_build_to_fail(code):
temp = tempfile.NamedTemporaryFile(mode='w')
temp.write(code)
temp.flush()
os.fsync(temp.fileno())
process = subprocess.Popen(
[
"nix-build",
"--impure",
"--keep-going",
"--no-link",
"--expr",
f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"],
stderr=subprocess.PIPE,
text=True)
stderr = ""
while True:
line = process.stderr.readline()
if not line:
break
stderr += line
print(line.strip())
process.wait()
temp.close()
return stderr
def get_artifact_hashes(flutter_compact_version):
code = load_code("get-artifact-hashes.nix",
nixpkgs_root=NIXPKGS_ROOT,
flutter_compact_version=flutter_compact_version)
stderr = nix_build_to_fail(code)
pattern = re.compile(
r"/nix/store/.*-flutter-artifacts-(.+?)-(.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n")
matches = pattern.findall(stderr)
result_dict = {}
for match in matches:
flutter_platform, architecture, got = match
result_dict.setdefault(flutter_platform, {})[architecture] = got
def sort_dict_recursive(d):
return {
k: sort_dict_recursive(v) if isinstance(
v, dict) else v for k, v in sorted(
d.items())}
result_dict = sort_dict_recursive(result_dict)
return result_dict
def get_dart_hashes(dart_version):
platforms = [
"x86_64-linux",
"aarch64-linux",
"x86_64-darwin",
"aarch64-darwin"]
result_dict = {}
for platform in platforms:
code = load_code(
"get-dart-hashes.nix",
dart_version=dart_version,
platform=platform)
stderr = nix_build_to_fail(code)
pattern = re.compile(r"got:\s+(.+?)\n")
result_dict[platform] = pattern.findall(stderr)[0]
return result_dict
def get_flutter_hash_and_src(flutter_version):
code = load_code(
"get-flutter.nix",
flutter_version=flutter_version,
hash="")
stderr = nix_build_to_fail(code)
pattern = re.compile(r"got:\s+(.+?)\n")
hash = pattern.findall(stderr)[0]
code = load_code(
"get-flutter.nix",
flutter_version=flutter_version,
hash=hash)
return (hash, nix_build(code))
def get_pubspec_lock(flutter_compact_version, flutter_src):
code = load_code(
"get-pubspec-lock.nix",
flutter_compact_version=flutter_compact_version,
flutter_src=flutter_src,
hash="")
stderr = nix_build_to_fail(code)
pattern = re.compile(r"got:\s+(.+?)\n")
hash = pattern.findall(stderr)[0]
code = load_code(
"get-pubspec-lock.nix",
flutter_compact_version=flutter_compact_version,
flutter_src=flutter_src,
hash=hash)
pubspec_lock_file = nix_build(code)
with open(pubspec_lock_file, 'r') as f:
pubspec_lock_yaml = f.read()
return yaml.safe_load(pubspec_lock_yaml)
def write_data(
nixpkgs_flutter_version_directory,
flutter_version,
engine_hash,
dart_version,
dart_hash,
flutter_hash,
artifact_hashes,
pubspec_lock):
with open(f"{nixpkgs_flutter_version_directory}/data.json", "w") as f:
f.write(json.dumps({
"version": flutter_version,
"engineVersion": engine_hash,
"dartVersion": dart_version,
"dartHash": dart_hash,
"flutterHash": flutter_hash,
"artifactHashes": artifact_hashes,
"pubspecLock": pubspec_lock,
}, indent=2).strip() + "\n")
def update_all_packages():
versions_directory = f"{NIXPKGS_ROOT}/pkgs/development/compilers/flutter/versions"
versions = [directory for directory in os.listdir(versions_directory)]
versions = sorted(versions, key=lambda x: (
int(x.split('_')[0]), int(x.split('_')[1])), reverse=True)
new_content = [
"flutterPackages = recurseIntoAttrs (callPackage ../development/compilers/flutter { });",
"flutter = flutterPackages.stable;",
] + [f"flutter{version.replace('_', '')} = flutterPackages.v{version};" for version in versions]
with open(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix", 'r') as file:
lines = file.read().splitlines(keepends=True)
start = -1
end = -1
for i, line in enumerate(lines):
if "flutterPackages = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line:
start = i
if start != -1 and len(line.strip()) == 0:
end = i
break
if start != -1 and end != -1:
del lines[start:end]
lines[start:start] = [f" {l}\n" for l in new_content]
with open(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix", 'w') as file:
file.write("".join(lines))
# Finds Flutter version, Dart version, and Engine hash.
# If the Flutter version is given, it uses that. Otherwise finds the
# latest stable Flutter version.
def find_versions(flutter_version=None):
engine_hash = None
dart_version = None
releases = json.load(urllib.request.urlopen(
"https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json"))
if not flutter_version:
stable_hash = releases['current_release']['stable']
release = next(
filter(
lambda release: release['hash'] == stable_hash,
releases['releases']))
flutter_version = release['version']
tags = subprocess.Popen(['git',
'ls-remote',
'--tags',
'https://github.com/flutter/engine.git'],
stdout=subprocess.PIPE,
text=True).communicate()[0].strip()
try:
engine_hash = next(
filter(
lambda line: line.endswith(f'refs/tags/{flutter_version}'),
tags.splitlines())).split('refs')[0].strip()
except StopIteration:
exit(
f"Couldn't find Engine hash for Flutter version: {flutter_version}")
try:
dart_version = next(
filter(
lambda release: release['version'] == flutter_version,
releases['releases']))['dart_sdk_version']
except StopIteration:
exit(
f"Couldn't find Dart version for Flutter version: {flutter_version}")
return (flutter_version, engine_hash, dart_version)
def main():
parser = argparse.ArgumentParser(description='Update Flutter in Nixpkgs')
parser.add_argument('--version', type=str, help='Specify Flutter version')
parser.add_argument('--artifact-hashes', action='store_true',
help='Whether to get artifact hashes')
args = parser.parse_args()
(flutter_version, engine_hash, dart_version) = find_versions(args.version)
flutter_compact_version = '_'.join(flutter_version.split('.')[:2])
if args.artifact_hashes:
print(
json.dumps(
get_artifact_hashes(flutter_compact_version),
indent=2).strip() +
"\n")
return
print(f"Flutter version: {flutter_version} ({flutter_compact_version})")
print(f"Engine hash: {engine_hash}")
print(f"Dart version: {dart_version}")
dart_hash = get_dart_hashes(dart_version)
(flutter_hash, flutter_src) = get_flutter_hash_and_src(flutter_version)
nixpkgs_flutter_version_directory = f"{NIXPKGS_ROOT}/pkgs/development/compilers/flutter/versions/{flutter_compact_version}"
if os.path.exists(f"{nixpkgs_flutter_version_directory}/data.json"):
os.remove(f"{nixpkgs_flutter_version_directory}/data.json")
os.makedirs(nixpkgs_flutter_version_directory, exist_ok=True)
update_all_packages()
common_data_args = {
"nixpkgs_flutter_version_directory": nixpkgs_flutter_version_directory,
"flutter_version": flutter_version,
"dart_version": dart_version,
"engine_hash": engine_hash,
"flutter_hash": flutter_hash,
"dart_hash": dart_hash,
}
write_data(
pubspec_lock={},
artifact_hashes={},
**common_data_args)
pubspec_lock = get_pubspec_lock(flutter_compact_version, flutter_src)
write_data(
pubspec_lock=pubspec_lock,
artifact_hashes={},
**common_data_args)
artifact_hashes = get_artifact_hashes(flutter_compact_version)
write_data(
pubspec_lock=pubspec_lock,
artifact_hashes=artifact_hashes,
**common_data_args)
if __name__ == "__main__":
main()