mirror of
https://github.com/Mic92/nix-update.git
synced 2024-09-17 13:27:27 +03:00
add support for flakes
This commit is contained in:
parent
73f7e7f036
commit
e5f57c258c
@ -14,6 +14,7 @@ designed to work with nixpkgs but also other package sets.
|
||||
- update buildRustPackage's cargoHash/cargoSha256 and cargoSetupHook's cargoDeps
|
||||
- update buildGoModule's vendorHash/vendorSha256
|
||||
- update buildNpmPackage's npmDepsHash and npmConfigHook's npmDeps
|
||||
- update flake outputs (see `--flake`)
|
||||
- build and run the resulting package (see `--build`,
|
||||
`--run` or `--shell`
|
||||
- commit updated files (see `--commit` flag)
|
||||
|
@ -20,6 +20,9 @@ def parse_args(args: list[str]) -> Options:
|
||||
parser = argparse.ArgumentParser()
|
||||
help = "File to import rather than default.nix. Examples, ./release.nix"
|
||||
parser.add_argument("-f", "--file", default="./.", help=help)
|
||||
parser.add_argument(
|
||||
"-F", "--flake", action="store_true", help="Update a flake attribute instead"
|
||||
)
|
||||
parser.add_argument("--build", action="store_true", help="build the package")
|
||||
parser.add_argument(
|
||||
"--test", action="store_true", help="Run package's `passthru.tests`"
|
||||
@ -68,7 +71,8 @@ def parse_args(args: list[str]) -> Options:
|
||||
parser.add_argument("attribute", help="Attribute name within the file evaluated")
|
||||
a = parser.parse_args(args)
|
||||
return Options(
|
||||
import_path=a.file,
|
||||
import_path=os.path.realpath(a.file),
|
||||
flake=a.flake,
|
||||
build=a.build,
|
||||
commit=a.commit,
|
||||
use_update_script=a.use_update_script,
|
||||
@ -87,13 +91,25 @@ def parse_args(args: list[str]) -> Options:
|
||||
|
||||
|
||||
def nix_shell(options: Options) -> None:
|
||||
import_path = os.path.realpath(options.import_path)
|
||||
expr = f"with import {import_path} {{}}; mkShell {{ buildInputs = [ {options.attribute} ]; }}"
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
path = os.path.join(d, "default.nix")
|
||||
with open(path, "w") as f:
|
||||
f.write(expr)
|
||||
run(["nix-shell", path], stdout=None, check=False)
|
||||
if options.flake:
|
||||
run(
|
||||
[
|
||||
"nix",
|
||||
"shell",
|
||||
f"{options.import_path}#{options.attribute}",
|
||||
"--extra-experimental-features",
|
||||
"flakes nix-command",
|
||||
],
|
||||
stdout=None,
|
||||
check=False,
|
||||
)
|
||||
else:
|
||||
expr = f"with import {options.import_path} {{}}; mkShell {{ buildInputs = [ {options.attribute} ]; }}"
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
path = os.path.join(d, "default.nix")
|
||||
with open(path, "w") as f:
|
||||
f.write(expr)
|
||||
run(["nix-shell", path], stdout=None, check=False)
|
||||
|
||||
|
||||
def git_has_diff(git_dir: str, package: Package) -> bool:
|
||||
@ -172,37 +188,69 @@ def validate_git_dir(import_path: str) -> str:
|
||||
|
||||
|
||||
def nix_run(options: Options) -> None:
|
||||
cmd = ["nix", "shell", "--extra-experimental-features", "nix-command"]
|
||||
cmd = (
|
||||
[
|
||||
"nix",
|
||||
"shell",
|
||||
"--extra-experimental-features",
|
||||
"flakes nix-command",
|
||||
f"{options.import_path}#{options.attribute}",
|
||||
]
|
||||
if options.flake
|
||||
else [
|
||||
"nix",
|
||||
"shell",
|
||||
"--extra-experimental-features",
|
||||
"nix-command",
|
||||
"-f",
|
||||
options.import_path,
|
||||
options.attribute,
|
||||
]
|
||||
)
|
||||
run(
|
||||
cmd + ["-f", options.import_path, options.attribute],
|
||||
cmd,
|
||||
stdout=None,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
def nix_build(options: Options) -> None:
|
||||
cmd = [
|
||||
"nix",
|
||||
"build",
|
||||
"--extra-experimental-features",
|
||||
"nix-command",
|
||||
"-L",
|
||||
"-f",
|
||||
options.import_path,
|
||||
options.attribute,
|
||||
]
|
||||
cmd = (
|
||||
[
|
||||
"nix",
|
||||
"shell",
|
||||
"--extra-experimental-features",
|
||||
"flakes nix-command",
|
||||
f"{options.import_path}#{options.attribute}",
|
||||
]
|
||||
if options.flake
|
||||
else [
|
||||
"nix",
|
||||
"build",
|
||||
"--extra-experimental-features",
|
||||
"nix-command",
|
||||
"-L",
|
||||
"-f",
|
||||
options.import_path,
|
||||
options.attribute,
|
||||
]
|
||||
)
|
||||
run(cmd, stdout=None)
|
||||
|
||||
|
||||
def nix_test(package: Package) -> None:
|
||||
def nix_test(opts: Options, package: Package) -> None:
|
||||
if not package.tests:
|
||||
die(f"Package '{package.name}' does not define any tests")
|
||||
|
||||
tests = []
|
||||
for t in package.tests:
|
||||
tests.append("-A")
|
||||
tests.append(f"{package.attribute}.tests.{t}")
|
||||
cmd = ["nix-build"] + tests
|
||||
if opts.flake:
|
||||
cmd = ["nix", "build", "--experimental-features", "flakes nix-command"]
|
||||
for t in package.tests:
|
||||
cmd.append(f"{opts.import_path}#{package.attribute}.tests.{t}")
|
||||
else:
|
||||
cmd = ["nix-build"]
|
||||
for t in package.tests:
|
||||
cmd.append("-A")
|
||||
cmd.append(f"{package.attribute}.tests.{t}")
|
||||
run(cmd, stdout=None)
|
||||
|
||||
|
||||
@ -251,10 +299,13 @@ def main(args: list[str] = sys.argv[1:]) -> None:
|
||||
return
|
||||
|
||||
if options.test:
|
||||
nix_test(package)
|
||||
nix_test(options, package)
|
||||
|
||||
if options.review:
|
||||
nixpkgs_review()
|
||||
if options.flake:
|
||||
print("--review is unsupporetd with --flake")
|
||||
else:
|
||||
nixpkgs_review()
|
||||
|
||||
if options.format:
|
||||
nixpkgs_fmt(package, git_dir)
|
||||
|
@ -53,43 +53,59 @@ class Package:
|
||||
self.version_position = Position(**raw_version_position)
|
||||
|
||||
|
||||
def eval_expression(import_path: str, attr: str) -> str:
|
||||
return f"""(
|
||||
let
|
||||
inputs = (if (builtins.hasAttr "overlays" (builtins.functionArgs (import {import_path}))) then {{ overlays = []; }} else {{ }});
|
||||
in
|
||||
with import {import_path} inputs;
|
||||
let
|
||||
pkg = {attr};
|
||||
raw_version_position = builtins.unsafeGetAttrPos "version" pkg;
|
||||
def eval_expression(import_path: str, attr: str, flake: bool) -> str:
|
||||
let_bindings = (
|
||||
f"""inherit (builtins) currentSystem getFlake stringLength substring;
|
||||
flake = getFlake "{import_path}";
|
||||
pkg = flake.packages.${{currentSystem}}.{attr} or flake.{attr};
|
||||
inherit (flake) outPath;
|
||||
outPathLen = stringLength outPath;
|
||||
sanitizePosition = {{ file, ... }}@pos:
|
||||
assert substring 0 outPathLen file == outPath;
|
||||
pos // {{ file = "{import_path}" + substring outPathLen (stringLength file - outPathLen) file; }};"""
|
||||
if flake
|
||||
else f"""
|
||||
inputs = if (builtins.functionArgs (import {import_path})) ? overlays then {{ overlays = [ ]; }} else {{ }};
|
||||
pkg = (import {import_path} inputs).{attr};
|
||||
sanitizePosition = x: x;"""
|
||||
)
|
||||
|
||||
position = if pkg ? isRubyGem then
|
||||
raw_version_position
|
||||
else
|
||||
builtins.unsafeGetAttrPos "src" pkg;
|
||||
in {{
|
||||
name = pkg.name;
|
||||
old_version = pkg.version or (builtins.parseDrvName pkg.name).version;
|
||||
inherit raw_version_position;
|
||||
filename = position.file;
|
||||
line = position.line;
|
||||
urls = pkg.src.urls or null;
|
||||
url = pkg.src.url or null;
|
||||
rev = pkg.src.rev or null;
|
||||
hash = pkg.src.outputHash or null;
|
||||
vendor_hash = pkg.vendorHash or null;
|
||||
vendor_sha256 = pkg.vendorSha256 or null;
|
||||
cargo_deps = (pkg.cargoDeps or null).outputHash or null;
|
||||
npm_deps = (pkg.npmDeps or null).outputHash or null;
|
||||
tests = builtins.attrNames (pkg.passthru.tests or {{}});
|
||||
has_update_script = pkg.passthru.updateScript or null != null;
|
||||
src_homepage = pkg.src.meta.homepage or null;
|
||||
changelog = pkg.meta.changelog or null;
|
||||
}})"""
|
||||
has_update_script = (
|
||||
"false" if flake else "pkg.passthru.updateScript or null != null"
|
||||
)
|
||||
|
||||
return f"""
|
||||
let
|
||||
{let_bindings}
|
||||
raw_version_position = sanitizePosition (builtins.unsafeGetAttrPos "version" pkg);
|
||||
|
||||
position = if pkg ? isRubyGem then
|
||||
raw_version_position
|
||||
else
|
||||
sanitizePosition (builtins.unsafeGetAttrPos "src" pkg);
|
||||
in {{
|
||||
name = pkg.name;
|
||||
old_version = pkg.version or (builtins.parseDrvName pkg.name).version;
|
||||
inherit raw_version_position;
|
||||
filename = position.file;
|
||||
line = position.line;
|
||||
urls = pkg.src.urls or null;
|
||||
url = pkg.src.url or null;
|
||||
rev = pkg.src.rev or null;
|
||||
hash = pkg.src.outputHash or null;
|
||||
vendor_hash = pkg.vendorHash or null;
|
||||
vendor_sha256 = pkg.vendorSha256 or null;
|
||||
cargo_deps = pkg.cargoDeps.outputHash or null;
|
||||
npm_deps = pkg.npmDeps.outputHash or null;
|
||||
tests = builtins.attrNames (pkg.passthru.tests or {{}});
|
||||
has_update_script = {has_update_script};
|
||||
src_homepage = pkg.src.meta.homepage or null;
|
||||
changelog = pkg.meta.changelog or null;
|
||||
}}"""
|
||||
|
||||
|
||||
def eval_attr(opts: Options) -> Package:
|
||||
expr = eval_expression(opts.import_path, opts.attribute)
|
||||
expr = eval_expression(opts.import_path, opts.attribute, opts.flake)
|
||||
cmd = [
|
||||
"nix",
|
||||
"eval",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
@ -7,10 +8,11 @@ from .version.version import VersionPreference
|
||||
@dataclass
|
||||
class Options:
|
||||
attribute: str
|
||||
flake: bool = False
|
||||
version: str = "stable"
|
||||
version_preference: VersionPreference = VersionPreference.STABLE
|
||||
version_regex: str = "(.*)"
|
||||
import_path: str = "./."
|
||||
import_path: str = os.getcwd()
|
||||
override_filename: Optional[str] = None
|
||||
commit: bool = False
|
||||
use_update_script: bool = False
|
||||
|
@ -105,29 +105,31 @@ def disable_check_meta(opts: Options) -> str:
|
||||
return f'(if (builtins.hasAttr "config" (builtins.functionArgs (import {opts.import_path}))) then {{ config.checkMeta = false; overlays = []; }} else {{ }})'
|
||||
|
||||
|
||||
def update_src_hash(opts: Options, filename: str, current_hash: str) -> None:
|
||||
expr = (
|
||||
f"(import {opts.import_path} {disable_check_meta(opts)}).{opts.attribute}.src"
|
||||
def get_attr(opts: Options, attr: str) -> str:
|
||||
return (
|
||||
f'let flake = builtins.getFlake "{opts.import_path}"; in (flake.packages.${{builtins.currentSystem}}.{opts.attribute} or flake.{opts.attribute}).{attr}'
|
||||
if opts.flake
|
||||
else f"(import {opts.import_path} {disable_check_meta(opts)}).{opts.attribute}.{attr}"
|
||||
)
|
||||
target_hash = nix_prefetch(expr)
|
||||
|
||||
|
||||
def update_src_hash(opts: Options, filename: str, current_hash: str) -> None:
|
||||
target_hash = nix_prefetch(get_attr(opts, "src"))
|
||||
replace_hash(filename, current_hash, target_hash)
|
||||
|
||||
|
||||
def update_go_modules_hash(opts: Options, filename: str, current_hash: str) -> None:
|
||||
expr = f"(import {opts.import_path} {disable_check_meta(opts)}).{opts.attribute}.go-modules"
|
||||
target_hash = nix_prefetch(expr)
|
||||
target_hash = nix_prefetch(get_attr(opts, "go-modules"))
|
||||
replace_hash(filename, current_hash, target_hash)
|
||||
|
||||
|
||||
def update_cargo_deps_hash(opts: Options, filename: str, current_hash: str) -> None:
|
||||
expr = f"(import {opts.import_path} {disable_check_meta(opts)}).{opts.attribute}.cargoDeps"
|
||||
target_hash = nix_prefetch(expr)
|
||||
target_hash = nix_prefetch(get_attr(opts, "cargoDeps"))
|
||||
replace_hash(filename, current_hash, target_hash)
|
||||
|
||||
|
||||
def update_npm_deps_hash(opts: Options, filename: str, current_hash: str) -> None:
|
||||
expr = f"(import {opts.import_path} {disable_check_meta(opts)}).{opts.attribute}.npmDeps"
|
||||
target_hash = nix_prefetch(expr)
|
||||
target_hash = nix_prefetch(get_attr(opts, "npmDeps"))
|
||||
replace_hash(filename, current_hash, target_hash)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user