Loading pkgs/development/compilers/flutter/update/update.py +226 −160 Original line number Diff line number Diff line #! /usr/bin/env nix-shell #! nix-shell -i python3 -p python3Packages.pyyaml import shutil import argparse import json import urllib.request import tempfile from sys import exit import os import subprocess import re import json import argparse import subprocess import sys import tempfile import urllib.request from pathlib import Path import yaml import json FAKE_HASH = 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' FAKE_HASH = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" NIXPKGS_ROOT = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE, text=True).communicate()[0].strip() 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: with Path( f"{NIXPKGS_ROOT}/pkgs/development/compilers/flutter/update/{name}.in" ).open("r", encoding="utf-8") as f: code = f.read() for (key, value) in kwargs.items(): for key, value in kwargs.items(): code = code.replace(f"@{key}@", value) return code Loading @@ -35,10 +38,11 @@ def load_code(name, **kwargs): # Return out paths def nix_build(code): temp = tempfile.NamedTemporaryFile(mode='w') with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as temp: temp.write(code) temp.flush() os.fsync(temp.fileno()) temp_name = temp.name process = subprocess.Popen( [ Loading @@ -46,21 +50,24 @@ def nix_build(code): "--impure", "--no-out-link", "--expr", f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"], f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp_name} {{}}", ], stdout=subprocess.PIPE, text=True) text=True, ) process.wait() temp.close() Path(temp_name).unlink() # Clean up the temporary file return process.stdout.read().strip().splitlines()[0] # Return errors def nix_build_to_fail(code): temp = tempfile.NamedTemporaryFile(mode='w') with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as temp: temp.write(code) temp.flush() os.fsync(temp.fileno()) temp_name = temp.name process = subprocess.Popen( [ Loading @@ -69,9 +76,11 @@ def nix_build_to_fail(code): "--keep-going", "--no-link", "--expr", f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"], f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp_name} {{}}", ], stderr=subprocess.PIPE, text=True) text=True, ) stderr = "" while True: Loading @@ -82,20 +91,23 @@ def nix_build_to_fail(code): print(line.strip()) process.wait() temp.close() Path(temp_name).unlink() # Clean up the temporary file return stderr def get_engine_hashes(engine_version, flutter_version): code = load_code("get-engine-hashes.nix", code = load_code( "get-engine-hashes.nix", nixpkgs_root=NIXPKGS_ROOT, flutter_version=flutter_version, engine_version=engine_version) engine_version=engine_version, ) stderr = nix_build_to_fail(code) pattern = re.compile( rf"/nix/store/.*-flutter-engine-source-{engine_version}-(.+?-.+?)-(.+?-.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n") rf"/nix/store/.*-flutter-engine-source-{engine_version}-(.+?-.+?)-(.+?-.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n" ) matches = pattern.findall(stderr) result_dict = {} Loading @@ -105,23 +117,25 @@ def get_engine_hashes(engine_version, flutter_version): 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) k: sort_dict_recursive(v) if isinstance(v, dict) else v for k, v in sorted(d.items()) } return result_dict return sort_dict_recursive(result_dict) def get_artifact_hashes(flutter_compact_version): code = load_code("get-artifact-hashes.nix", code = load_code( "get-artifact-hashes.nix", nixpkgs_root=NIXPKGS_ROOT, flutter_compact_version=flutter_compact_version) 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") r"/nix/store/.*-flutter-artifacts-(.+?)-(.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n" ) matches = pattern.findall(stderr) result_dict = {} Loading @@ -131,27 +145,23 @@ def get_artifact_hashes(flutter_compact_version): 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) k: sort_dict_recursive(v) if isinstance(v, dict) else v for k, v in sorted(d.items()) } return result_dict return sort_dict_recursive(result_dict) def get_dart_hashes(dart_version, channel): platforms = [ "x86_64-linux", "aarch64-linux", "x86_64-darwin", "aarch64-darwin"] 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, channel=channel, platform=platform) platform=platform, ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") Loading @@ -161,21 +171,17 @@ def get_dart_hashes(dart_version, channel): def get_flutter_hash_and_src(flutter_version): code = load_code( "get-flutter.nix", flutter_version=flutter_version, hash="") 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] flutter_hash_value = pattern.findall(stderr)[0] code = load_code( "get-flutter.nix", flutter_version=flutter_version, hash=hash) "get-flutter.nix", flutter_version=flutter_version, hash=flutter_hash_value ) return (hash, nix_build(code)) return (flutter_hash_value, nix_build(code)) def get_pubspec_lock(flutter_compact_version, flutter_src): Loading @@ -183,42 +189,51 @@ def get_pubspec_lock(flutter_compact_version, flutter_src): "get-pubspec-lock.nix", flutter_compact_version=flutter_compact_version, flutter_src=flutter_src, hash="") hash="", ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") hash = pattern.findall(stderr)[0] pubspec_lock_hash = pattern.findall(stderr)[0] code = load_code( "get-pubspec-lock.nix", flutter_compact_version=flutter_compact_version, flutter_src=flutter_src, hash=hash) hash=pubspec_lock_hash, ) pubspec_lock_file = nix_build(code) with open(pubspec_lock_file, 'r') as f: with Path(pubspec_lock_file).open("r", encoding="utf-8") as f: pubspec_lock_yaml = f.read() return yaml.safe_load(pubspec_lock_yaml) def get_engine_swiftshader_rev(engine_version): with urllib.request.urlopen(f"https://github.com/flutter/flutter/raw/{engine_version}/DEPS") as f: deps = f.read().decode('utf-8') pattern = re.compile(r"Var\('swiftshader_git'\) \+ '\/SwiftShader\.git' \+ '@' \+ \'([0-9a-fA-F]{40})\'\,") rev = pattern.findall(deps)[0] return rev with urllib.request.urlopen( f"https://github.com/flutter/flutter/raw/{engine_version}/DEPS" ) as f: deps = f.read().decode("utf-8") pattern = re.compile( r"Var\('swiftshader_git'\) \+ '\/SwiftShader\.git' \+ '@' \+ \'([0-9a-fA-F]{40})\'\," ) return pattern.findall(deps)[0] def get_engine_swiftshader_hash(engine_swiftshader_rev): code = load_code( "get-engine-swiftshader.nix", engine_swiftshader_rev=engine_swiftshader_rev, hash="") hash="", ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") return pattern.findall(stderr)[0] def write_data( nixpkgs_flutter_version_directory, flutter_version, Loading @@ -231,9 +246,14 @@ def write_data( dart_hash, flutter_hash, artifact_hashes, pubspec_lock): with open(f"{nixpkgs_flutter_version_directory}/data.json", "w") as f: f.write(json.dumps({ pubspec_lock, ): with Path(f"{nixpkgs_flutter_version_directory}/data.json").open( "w", encoding="utf-8" ) as f: f.write( json.dumps( { "version": flutter_version, "engineVersion": engine_hash, "engineSwiftShaderHash": engine_swiftshader_hash, Loading @@ -245,29 +265,44 @@ def write_data( "flutterHash": flutter_hash, "artifactHashes": artifact_hashes, "pubspecLock": pubspec_lock, }, indent=2).strip() + "\n") }, 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) versions = [d.name for d in Path(versions_directory).iterdir()] versions = sorted( versions, key=lambda x: (int(x.split("_")[0]), int(x.split("_")[1])), reverse=True, ) new_content = [ "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });", "flutterPackages-source = recurseIntoAttrs (callPackage ../development/compilers/flutter { useNixpkgsEngine = true; });", "flutterPackages = flutterPackages-bin;", "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: ] + [ f"flutter{version.replace('_', '')} = flutterPackages.v{version};" for version in versions ] with Path(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix").open( "r", encoding="utf-8" ) as file: lines = file.read().splitlines(keepends=True) start = -1 end = -1 for i, line in enumerate(lines): if "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line: if ( "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line ): start = i if start != -1 and len(line.strip()) == 0: end = i Loading @@ -275,9 +310,11 @@ def update_all_packages(): if start != -1 and end != -1: del lines[start:end] lines[start:start] = [f" {l}\n" for l in new_content] lines[start:start] = [f" {line}\n" for line in new_content] with open(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix", 'w') as file: with Path(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix").open( "w", encoding="utf-8" ) as file: file.write("".join(lines)) Loading @@ -288,74 +325,98 @@ def find_versions(flutter_version=None, channel=None): engine_hash = None dart_version = None releases = json.load(urllib.request.urlopen( "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json")) releases = json.load( urllib.request.urlopen( "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" ) ) if not channel: channel = 'stable' channel = "stable" if not flutter_version: hash = releases['current_release'][channel] release_hash = releases["current_release"][channel] release = next( filter( lambda release: release['hash'] == hash, releases['releases'])) flutter_version = release['version'] tags = subprocess.Popen(['git', 'ls-remote', '--tags', 'https://github.com/flutter/flutter.git'], lambda release: release["hash"] == release_hash, releases["releases"] ) ) flutter_version = release["version"] tags = ( subprocess.Popen( ["git", "ls-remote", "--tags", "https://github.com/flutter/flutter.git"], stdout=subprocess.PIPE, text=True).communicate()[0].strip() text=True, ) .communicate()[0] .strip() ) try: flutter_hash = next( flutter_hash = ( next( filter( lambda line: line.endswith(f'refs/tags/{flutter_version}'), tags.splitlines())).split('refs')[0].strip() engine_hash = urllib.request.urlopen(f'https://github.com/flutter/flutter/raw/{flutter_hash}/bin/internal/engine.version').read().decode('utf-8').strip() lambda line: line.endswith(f"refs/tags/{flutter_version}"), tags.splitlines(), ) ) .split("refs")[0] .strip() ) engine_hash = ( urllib.request.urlopen( f"https://github.com/flutter/flutter/raw/{flutter_hash}/bin/internal/engine.version" ) .read() .decode("utf-8") .strip() ) except StopIteration: exit( f"Couldn't find Engine hash for Flutter version: {flutter_version}") sys.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'] lambda release: release["version"] == flutter_version, releases["releases"], ) )["dart_sdk_version"] if " " in dart_version: dart_version = dart_version.split(' ')[2][:-1] dart_version = dart_version.split(" ")[2][:-1] except StopIteration: exit( f"Couldn't find Dart version for Flutter version: {flutter_version}") sys.exit(f"Couldn't find Dart version for Flutter version: {flutter_version}") return (flutter_version, engine_hash, dart_version, channel) def main(): parser = argparse.ArgumentParser(description='Update Flutter in Nixpkgs') parser.add_argument('--version', type=str, help='Specify Flutter version') parser.add_argument('--channel', type=str, help='Specify Flutter release channel') parser.add_argument('--artifact-hashes', action='store_true', help='Whether to get artifact hashes') parser = argparse.ArgumentParser(description="Update Flutter in Nixpkgs") parser.add_argument("--version", type=str, help="Specify Flutter version") parser.add_argument("--channel", type=str, help="Specify Flutter release channel") parser.add_argument( "--artifact-hashes", action="store_true", help="Whether to get artifact hashes" ) args = parser.parse_args() (flutter_version, engine_hash, dart_version, channel) = find_versions(args.version, args.channel) (flutter_version, engine_hash, dart_version, channel) = find_versions( args.version, args.channel ) flutter_compact_version = '_'.join(flutter_version.split('.')[:2]) 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") json.dumps(get_artifact_hashes(flutter_compact_version), indent=2).strip() + "\n" ) return print(f"Flutter version: {flutter_version} ({flutter_compact_version}) on ({channel})") print( f"Flutter version: {flutter_version} ({flutter_compact_version}) on ({channel})" ) print(f"Engine hash: {engine_hash}") print(f"Dart version: {dart_version}") Loading @@ -364,9 +425,9 @@ def main(): 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) if Path(f"{nixpkgs_flutter_version_directory}/data.json").exists(): Path(f"{nixpkgs_flutter_version_directory}/data.json").unlink() Path(nixpkgs_flutter_version_directory).mkdir(parents=True, exist_ok=True) update_all_packages() Loading @@ -385,8 +446,9 @@ def main(): artifact_hashes={}, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) pubspec_lock = get_pubspec_lock(flutter_compact_version, flutter_src) Loading @@ -395,8 +457,9 @@ def main(): artifact_hashes={}, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) artifact_hashes = get_artifact_hashes(flutter_compact_version) Loading @@ -405,8 +468,9 @@ def main(): artifact_hashes=artifact_hashes, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) engine_hashes = get_engine_hashes(engine_hash, flutter_version) Loading @@ -415,8 +479,9 @@ def main(): artifact_hashes=artifact_hashes, engine_hashes=engine_hashes, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) engine_swiftshader_rev = get_engine_swiftshader_rev(engine_hash) engine_swiftshader_hash = get_engine_swiftshader_hash(engine_swiftshader_rev) Loading @@ -427,7 +492,8 @@ def main(): engine_hashes=engine_hashes, engine_swiftshader_hash=engine_swiftshader_hash, engine_swiftshader_rev=engine_swiftshader_rev, **common_data_args) **common_data_args, ) if __name__ == "__main__": Loading Loading
pkgs/development/compilers/flutter/update/update.py +226 −160 Original line number Diff line number Diff line #! /usr/bin/env nix-shell #! nix-shell -i python3 -p python3Packages.pyyaml import shutil import argparse import json import urllib.request import tempfile from sys import exit import os import subprocess import re import json import argparse import subprocess import sys import tempfile import urllib.request from pathlib import Path import yaml import json FAKE_HASH = 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' FAKE_HASH = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" NIXPKGS_ROOT = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE, text=True).communicate()[0].strip() 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: with Path( f"{NIXPKGS_ROOT}/pkgs/development/compilers/flutter/update/{name}.in" ).open("r", encoding="utf-8") as f: code = f.read() for (key, value) in kwargs.items(): for key, value in kwargs.items(): code = code.replace(f"@{key}@", value) return code Loading @@ -35,10 +38,11 @@ def load_code(name, **kwargs): # Return out paths def nix_build(code): temp = tempfile.NamedTemporaryFile(mode='w') with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as temp: temp.write(code) temp.flush() os.fsync(temp.fileno()) temp_name = temp.name process = subprocess.Popen( [ Loading @@ -46,21 +50,24 @@ def nix_build(code): "--impure", "--no-out-link", "--expr", f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"], f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp_name} {{}}", ], stdout=subprocess.PIPE, text=True) text=True, ) process.wait() temp.close() Path(temp_name).unlink() # Clean up the temporary file return process.stdout.read().strip().splitlines()[0] # Return errors def nix_build_to_fail(code): temp = tempfile.NamedTemporaryFile(mode='w') with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as temp: temp.write(code) temp.flush() os.fsync(temp.fileno()) temp_name = temp.name process = subprocess.Popen( [ Loading @@ -69,9 +76,11 @@ def nix_build_to_fail(code): "--keep-going", "--no-link", "--expr", f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp.name} {{}}"], f"with import {NIXPKGS_ROOT} {{}}; callPackage {temp_name} {{}}", ], stderr=subprocess.PIPE, text=True) text=True, ) stderr = "" while True: Loading @@ -82,20 +91,23 @@ def nix_build_to_fail(code): print(line.strip()) process.wait() temp.close() Path(temp_name).unlink() # Clean up the temporary file return stderr def get_engine_hashes(engine_version, flutter_version): code = load_code("get-engine-hashes.nix", code = load_code( "get-engine-hashes.nix", nixpkgs_root=NIXPKGS_ROOT, flutter_version=flutter_version, engine_version=engine_version) engine_version=engine_version, ) stderr = nix_build_to_fail(code) pattern = re.compile( rf"/nix/store/.*-flutter-engine-source-{engine_version}-(.+?-.+?)-(.+?-.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n") rf"/nix/store/.*-flutter-engine-source-{engine_version}-(.+?-.+?)-(.+?-.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n" ) matches = pattern.findall(stderr) result_dict = {} Loading @@ -105,23 +117,25 @@ def get_engine_hashes(engine_version, flutter_version): 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) k: sort_dict_recursive(v) if isinstance(v, dict) else v for k, v in sorted(d.items()) } return result_dict return sort_dict_recursive(result_dict) def get_artifact_hashes(flutter_compact_version): code = load_code("get-artifact-hashes.nix", code = load_code( "get-artifact-hashes.nix", nixpkgs_root=NIXPKGS_ROOT, flutter_compact_version=flutter_compact_version) 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") r"/nix/store/.*-flutter-artifacts-(.+?)-(.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n" ) matches = pattern.findall(stderr) result_dict = {} Loading @@ -131,27 +145,23 @@ def get_artifact_hashes(flutter_compact_version): 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) k: sort_dict_recursive(v) if isinstance(v, dict) else v for k, v in sorted(d.items()) } return result_dict return sort_dict_recursive(result_dict) def get_dart_hashes(dart_version, channel): platforms = [ "x86_64-linux", "aarch64-linux", "x86_64-darwin", "aarch64-darwin"] 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, channel=channel, platform=platform) platform=platform, ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") Loading @@ -161,21 +171,17 @@ def get_dart_hashes(dart_version, channel): def get_flutter_hash_and_src(flutter_version): code = load_code( "get-flutter.nix", flutter_version=flutter_version, hash="") 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] flutter_hash_value = pattern.findall(stderr)[0] code = load_code( "get-flutter.nix", flutter_version=flutter_version, hash=hash) "get-flutter.nix", flutter_version=flutter_version, hash=flutter_hash_value ) return (hash, nix_build(code)) return (flutter_hash_value, nix_build(code)) def get_pubspec_lock(flutter_compact_version, flutter_src): Loading @@ -183,42 +189,51 @@ def get_pubspec_lock(flutter_compact_version, flutter_src): "get-pubspec-lock.nix", flutter_compact_version=flutter_compact_version, flutter_src=flutter_src, hash="") hash="", ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") hash = pattern.findall(stderr)[0] pubspec_lock_hash = pattern.findall(stderr)[0] code = load_code( "get-pubspec-lock.nix", flutter_compact_version=flutter_compact_version, flutter_src=flutter_src, hash=hash) hash=pubspec_lock_hash, ) pubspec_lock_file = nix_build(code) with open(pubspec_lock_file, 'r') as f: with Path(pubspec_lock_file).open("r", encoding="utf-8") as f: pubspec_lock_yaml = f.read() return yaml.safe_load(pubspec_lock_yaml) def get_engine_swiftshader_rev(engine_version): with urllib.request.urlopen(f"https://github.com/flutter/flutter/raw/{engine_version}/DEPS") as f: deps = f.read().decode('utf-8') pattern = re.compile(r"Var\('swiftshader_git'\) \+ '\/SwiftShader\.git' \+ '@' \+ \'([0-9a-fA-F]{40})\'\,") rev = pattern.findall(deps)[0] return rev with urllib.request.urlopen( f"https://github.com/flutter/flutter/raw/{engine_version}/DEPS" ) as f: deps = f.read().decode("utf-8") pattern = re.compile( r"Var\('swiftshader_git'\) \+ '\/SwiftShader\.git' \+ '@' \+ \'([0-9a-fA-F]{40})\'\," ) return pattern.findall(deps)[0] def get_engine_swiftshader_hash(engine_swiftshader_rev): code = load_code( "get-engine-swiftshader.nix", engine_swiftshader_rev=engine_swiftshader_rev, hash="") hash="", ) stderr = nix_build_to_fail(code) pattern = re.compile(r"got:\s+(.+?)\n") return pattern.findall(stderr)[0] def write_data( nixpkgs_flutter_version_directory, flutter_version, Loading @@ -231,9 +246,14 @@ def write_data( dart_hash, flutter_hash, artifact_hashes, pubspec_lock): with open(f"{nixpkgs_flutter_version_directory}/data.json", "w") as f: f.write(json.dumps({ pubspec_lock, ): with Path(f"{nixpkgs_flutter_version_directory}/data.json").open( "w", encoding="utf-8" ) as f: f.write( json.dumps( { "version": flutter_version, "engineVersion": engine_hash, "engineSwiftShaderHash": engine_swiftshader_hash, Loading @@ -245,29 +265,44 @@ def write_data( "flutterHash": flutter_hash, "artifactHashes": artifact_hashes, "pubspecLock": pubspec_lock, }, indent=2).strip() + "\n") }, 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) versions = [d.name for d in Path(versions_directory).iterdir()] versions = sorted( versions, key=lambda x: (int(x.split("_")[0]), int(x.split("_")[1])), reverse=True, ) new_content = [ "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });", "flutterPackages-source = recurseIntoAttrs (callPackage ../development/compilers/flutter { useNixpkgsEngine = true; });", "flutterPackages = flutterPackages-bin;", "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: ] + [ f"flutter{version.replace('_', '')} = flutterPackages.v{version};" for version in versions ] with Path(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix").open( "r", encoding="utf-8" ) as file: lines = file.read().splitlines(keepends=True) start = -1 end = -1 for i, line in enumerate(lines): if "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line: if ( "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line ): start = i if start != -1 and len(line.strip()) == 0: end = i Loading @@ -275,9 +310,11 @@ def update_all_packages(): if start != -1 and end != -1: del lines[start:end] lines[start:start] = [f" {l}\n" for l in new_content] lines[start:start] = [f" {line}\n" for line in new_content] with open(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix", 'w') as file: with Path(f"{NIXPKGS_ROOT}/pkgs/top-level/all-packages.nix").open( "w", encoding="utf-8" ) as file: file.write("".join(lines)) Loading @@ -288,74 +325,98 @@ def find_versions(flutter_version=None, channel=None): engine_hash = None dart_version = None releases = json.load(urllib.request.urlopen( "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json")) releases = json.load( urllib.request.urlopen( "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" ) ) if not channel: channel = 'stable' channel = "stable" if not flutter_version: hash = releases['current_release'][channel] release_hash = releases["current_release"][channel] release = next( filter( lambda release: release['hash'] == hash, releases['releases'])) flutter_version = release['version'] tags = subprocess.Popen(['git', 'ls-remote', '--tags', 'https://github.com/flutter/flutter.git'], lambda release: release["hash"] == release_hash, releases["releases"] ) ) flutter_version = release["version"] tags = ( subprocess.Popen( ["git", "ls-remote", "--tags", "https://github.com/flutter/flutter.git"], stdout=subprocess.PIPE, text=True).communicate()[0].strip() text=True, ) .communicate()[0] .strip() ) try: flutter_hash = next( flutter_hash = ( next( filter( lambda line: line.endswith(f'refs/tags/{flutter_version}'), tags.splitlines())).split('refs')[0].strip() engine_hash = urllib.request.urlopen(f'https://github.com/flutter/flutter/raw/{flutter_hash}/bin/internal/engine.version').read().decode('utf-8').strip() lambda line: line.endswith(f"refs/tags/{flutter_version}"), tags.splitlines(), ) ) .split("refs")[0] .strip() ) engine_hash = ( urllib.request.urlopen( f"https://github.com/flutter/flutter/raw/{flutter_hash}/bin/internal/engine.version" ) .read() .decode("utf-8") .strip() ) except StopIteration: exit( f"Couldn't find Engine hash for Flutter version: {flutter_version}") sys.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'] lambda release: release["version"] == flutter_version, releases["releases"], ) )["dart_sdk_version"] if " " in dart_version: dart_version = dart_version.split(' ')[2][:-1] dart_version = dart_version.split(" ")[2][:-1] except StopIteration: exit( f"Couldn't find Dart version for Flutter version: {flutter_version}") sys.exit(f"Couldn't find Dart version for Flutter version: {flutter_version}") return (flutter_version, engine_hash, dart_version, channel) def main(): parser = argparse.ArgumentParser(description='Update Flutter in Nixpkgs') parser.add_argument('--version', type=str, help='Specify Flutter version') parser.add_argument('--channel', type=str, help='Specify Flutter release channel') parser.add_argument('--artifact-hashes', action='store_true', help='Whether to get artifact hashes') parser = argparse.ArgumentParser(description="Update Flutter in Nixpkgs") parser.add_argument("--version", type=str, help="Specify Flutter version") parser.add_argument("--channel", type=str, help="Specify Flutter release channel") parser.add_argument( "--artifact-hashes", action="store_true", help="Whether to get artifact hashes" ) args = parser.parse_args() (flutter_version, engine_hash, dart_version, channel) = find_versions(args.version, args.channel) (flutter_version, engine_hash, dart_version, channel) = find_versions( args.version, args.channel ) flutter_compact_version = '_'.join(flutter_version.split('.')[:2]) 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") json.dumps(get_artifact_hashes(flutter_compact_version), indent=2).strip() + "\n" ) return print(f"Flutter version: {flutter_version} ({flutter_compact_version}) on ({channel})") print( f"Flutter version: {flutter_version} ({flutter_compact_version}) on ({channel})" ) print(f"Engine hash: {engine_hash}") print(f"Dart version: {dart_version}") Loading @@ -364,9 +425,9 @@ def main(): 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) if Path(f"{nixpkgs_flutter_version_directory}/data.json").exists(): Path(f"{nixpkgs_flutter_version_directory}/data.json").unlink() Path(nixpkgs_flutter_version_directory).mkdir(parents=True, exist_ok=True) update_all_packages() Loading @@ -385,8 +446,9 @@ def main(): artifact_hashes={}, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) pubspec_lock = get_pubspec_lock(flutter_compact_version, flutter_src) Loading @@ -395,8 +457,9 @@ def main(): artifact_hashes={}, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) artifact_hashes = get_artifact_hashes(flutter_compact_version) Loading @@ -405,8 +468,9 @@ def main(): artifact_hashes=artifact_hashes, engine_hashes={}, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) engine_hashes = get_engine_hashes(engine_hash, flutter_version) Loading @@ -415,8 +479,9 @@ def main(): artifact_hashes=artifact_hashes, engine_hashes=engine_hashes, engine_swiftshader_hash=FAKE_HASH, engine_swiftshader_rev='0', **common_data_args) engine_swiftshader_rev="0", **common_data_args, ) engine_swiftshader_rev = get_engine_swiftshader_rev(engine_hash) engine_swiftshader_hash = get_engine_swiftshader_hash(engine_swiftshader_rev) Loading @@ -427,7 +492,8 @@ def main(): engine_hashes=engine_hashes, engine_swiftshader_hash=engine_swiftshader_hash, engine_swiftshader_rev=engine_swiftshader_rev, **common_data_args) **common_data_args, ) if __name__ == "__main__": Loading