mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-14 14:10:33 +03:00

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.
339 lines
9.9 KiB
Python
Executable file
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()
|